Question

Here's the deal. I've set up my database with two tables that are more or less as follows (actually, my table is much more complex, but this is the gist):

TABLE `elements`

  • id
  • data

TABLE `element_drafts`

  • id
  • element_id
  • data

As you might be able to guess from the names, the second table contains rows that are drafts of rows in the first table. (Don't worry about recommending better ways to do the drafts =) my tables are more complex than shown, and having a drafts table is the best solution atm).

I've set up a relationship between the two tables so that I can do things like this:

// Get all of the elements along with their draft rows
$elements_with_drafts = Element::with('drafts')->all();

I'm also able to select only the elements that HAVE draft rows by doing this:

$elements_with_drafts = Element::with('drafts')
    ->whereIn('id', function($query)
    {
        $query->select('element_id')->from('element_drafts');
    })
    ->get();

But there's one thing that I'd like to do that I can't figure out: copying the draft values to their parent element.

In the end, my goal is to copy over all of the element_drafts['data'] values to their parent element['data'] field via a single query.

I'm not totally sure that this is even possible. Is it?

My guess is that somehow it might be done like this:

$elements_with_drafts = Element::with('drafts')
    ->whereIn('id', function($query)
    {
        $query->select('element_id')->from('element_drafts');
    })
    ->update(array("data" => function($query)
    {
        // Somehow select the draft value?
    });

I feel like I'm really close, but I'm not quite sure how to do what I want. Any ideas?

Note: obviously this could be accomplished relatively easily with a foreach loop, but I'm hoping for a solution that is just a single query.

Was it helpful?

Solution

Like @Ben's, only he made some mistakes:

DB::statement('UPDATE elements e
    JOIN element_drafts d ON e.id = d.element_id
    SET e.data = d.data');

In fact you can use Query Builder too:

DB::table('elements as e')
    ->join('element_drafts as d', 'd.element_id', '=', 'e.id')
    ->update(['e.data' => DB::raw('d.data')]);

Both will work just the same.

Mind that it will set e.data to d.data of first row joined (in case you have more drafts than one per element).

OTHER TIPS

DB::statement('UPDATE elements e
               JOIN drafts d
               SET e.data = d.data WHERE e.id = d.element_id');

EDIT: Check deczo's answer for a Query Builder solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top