问题
This topic is related to my previews one Join two tables with all records
I'm tryng now to join 3 or more tables in my Laravel controller code, and view them in one Datatable.
table1
+--------------------+---------+
| recordtime | tempout |
+--------------------+---------+
| 4.12.2020 10:00:00 | 1.1 |
| 4.12.2020 10:30:00 | 1.2 |
| 4.12.2020 11:00:00 | 1.3 |
| 4.12.2020 11:30:00 | 1.4 |
| 4.12.2020 12:00:00 | 1.5 |
+--------------------+---------+
table2
+--------------------+---------+
| recordtime | tempout |
+--------------------+---------+
| 4.12.2020 10:00:00 | 2.1 |
| 4.12.2020 11:00:00 | 2.3 |
| 4.12.2020 12:00:00 | 2.5 |
| 4.12.2020 13:00:00 | 2.6 |
| 4.12.2020 14:00:00 | 2.7 |
| 4.12.2020 16:00:00 | 2.9 |
+--------------------+---------+
table3
+--------------------+---------+
| recordtime | tempout |
+--------------------+---------+
| 4.12.2020 15:00:00 | 3.1 |
| 4.12.2020 16:00:00 | 3.3 |
+--------------------+---------+
The result needed is this:
+--------------------+---------+---------------+---------------+
| recordtime | tempout | tempoutstamb | tempoutstamb2 |
+--------------------+---------+---------------+---------------+
| 4.12.2020 10:00:00 | 1.1 | 2.1 | - |
| 4.12.2020 10:30:00 | 1.2 | - | - |
| 4.12.2020 11:00:00 | 1.3 | 2.3 | - |
| 4.12.2020 11:30:00 | 1.4 | - | - |
| 4.12.2020 12:00:00 | 1.5 | 2.5 | - |
| 4.12.2020 13:00:00 | - | 2.6 | - |
| 4.12.2020 14:00:00 | - | 2.7 | - |
| 4.12.2020 15:00:00 | - | - | 3.1 |
| 4.12.2020 16:00:00 | - | 2.9 | 3.3 |
+--------------------+---------+---------------+---------------+
The result need to have all records and is based on "recordtime" column.
I create the code for 2 tables. He is working us expected like in the table above:
$results2 = Tablemodel1::whereBetween('table1.recordtime', $dateScope)
->selectRaw('table1.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->leftJoin('table2', function($join){
$join->on('table1.recordtime', '=', 'table2.recordtime');
})
->groupBy('table1.recordtime');
$results = Tablemodel2::whereBetween('table2.recordtime', $dateScope)
->selectRaw('table2.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->leftJoin('table1', function($join){
$join->on('table1.recordtime', '=', 'table2.recordtime');
})
->groupBy('table2.recordtime')
->orderBy('recordtime', 'ASC')
->union($results2)
->get();
I tryed now to add the 3th column in $results3
variable and union it with others:
$results2 = Tablemodel1::whereBetween('table1.recordtime', $dateScope)
->selectRaw('table1.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->leftJoin('table2', function($join){
$join->on('table1.recordtime', '=', 'table2.recordtime');
})
->groupBy('table1.recordtime');
$results3 = Tablemodel3::whereBetween('table3.recordtime', $dateScope)
->selectRaw('table3.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table3.tempout) as tempoutstamb2')
->leftJoin('table1', function($join){
$join->on('table3.recordtime', '=', 'table2.recordtime');
})
->groupBy('table3.recordtime');
$results = Tablemodel2::whereBetween('table2.recordtime', $dateScope)
->selectRaw('table2.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->leftJoin('table1', function($join){
$join->on('table1.recordtime', '=', 'table2.recordtime');
})
->groupBy('table2.recordtime')
->orderBy('recordtime', 'ASC')
->union($results2)
->union($results3)
->get();
This gives me all records that need to be in column tempoutstamb2
are transfered wrongly in tempoutstamb
. Any Idea how to make it right?
Raw SQL answer is good too.
回答1:
You can solve it in easier way:
select ts recordtime, max(to1) tempout, max(to2) tempoutstamb, max(to3) tempoutstamb2
from (
select ts, tempout to1, cast (null as numeric(10,1)) to2, cast (null as numeric(10,1)) to3
from table1
union all
select ts, null, tempout, null
from table2
union all
select ts, null, null, tempout
from table3
) tt
group by ts
order by ts;
You can find it in fiddle https://www.db-fiddle.com/f/eJsPZijRnQFGXugLGHnn93/0
NOTE: I have assumed that null values displayed as '-' is just output formatting. If that is not the case output with NULL can be converted to '-'.
NOTE2: I do not know how to convert to Laravel/PHP code, hopefully you would have better idea.
回答2:
This method works great:
$results2 = Tablemodel1::whereBetween('table1.recordtime', $dateScope)
->selectRaw('table1.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->selectRaw('max(table3.tempout) as tempoutstamb2')
->leftJoin('table2','table1.recordtime', '=', 'table2.recordtime')
->leftJoin('table3','table1.recordtime', '=', 'table3.recordtime')
->groupBy('table1.recordtime');
$results3 = Tablemodel3::whereBetween('table3.recordtime', $dateScope)
->selectRaw('table3.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->selectRaw('max(table3.tempout) as tempoutstamb2')
->leftJoin('table1','table1.recordtime', '=', 'table3.recordtime')
->leftJoin('table2','table2.recordtime', '=', 'table3.recordtime')
->groupBy('table3.recordtime');
$results = Tablemodel2::whereBetween('table2.recordtime', $dateScope)
->selectRaw('table2.recordtime')
->selectRaw('max(table1.tempout) as tempout')
->selectRaw('max(table2.tempout) as tempoutstamb')
->selectRaw('max(table3.tempout) as tempoutstamb2')
->leftJoin('table1','table1.recordtime', '=', 'table2.recordtime')
->leftJoin('table3','table2.recordtime', '=', 'table3.recordtime')
->groupBy('table2.recordtime')
->union($results2)
->union($results3)
->orderBy('recordtime', 'ASC')
->get();
I will wait to mark my answer to solved, if soon there is no another answer with optimized code like using loop or something.
来源:https://stackoverflow.com/questions/65236765/outer-join-3-or-more-tables-in-laravel-8