Outer join 3 or more tables in Laravel 8

自古美人都是妖i 提交于 2021-01-07 06:31:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!