【问题标题】:Outer join 3 or more tables in Laravel 8Laravel 8中的外部连接3个或更多表
【发布时间】:2021-03-22 00:11:49
【问题描述】:

这个话题和我的预览有关Join two tables with all records

我现在尝试在我的 Laravel 控制器代码中加入 3 个或更多表,并在一个 Datatable 中查看它们。

表1

+--------------------+---------+
|     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 |
+--------------------+---------+

表2

+--------------------+---------+
|     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 |
+--------------------+---------+

表3

+--------------------+---------+
|     recordtime     | tempout |
+--------------------+---------+
| 4.12.2020 15:00:00 |     3.1 |
| 4.12.2020 16:00:00 |     3.3 |
+--------------------+---------+

需要的结果是这样的:

+--------------------+---------+---------------+---------------+
|     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           |
+--------------------+---------+---------------+---------------+

结果需要有所有记录,并且基于“记录时间”列。

我为 2 个表创建代码。他正在按照我们预期的方式工作,如上表所示:

  $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();

我现在尝试在$results3 变量中添加第 3 列并将其与其他列联合:

  $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();

这给了我所有需要在列tempoutstamb2 中的记录在tempoutstamb 中错误地传输。任何想法如何使它正确?

原始 SQL 答案也很好。

【问题讨论】:

    标签: laravel postgresql left-join union full-outer-join


    【解决方案1】:

    你可以用更简单的方法解决它:

    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; 
    

    你可以在小提琴https://www.db-fiddle.com/f/eJsPZijRnQFGXugLGHnn93/0找到它

    注意:我假设显示为“-”的空值只是输出格式。 如果不是这种情况,可以将带有 NULL 的输出转换为 '-'。

    注意2:我不知道如何转换为 Laravel/PHP 代码,希望你有更好的主意。

    【讨论】:

    • 什么是to1,to2,to3, ts?
    • @HristianYordanov 是 table1、table2、table3。我刚刚改了名字。
    【解决方案2】:

    这个方法效果很好:

      $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();
    

    我会等待将我的答案标记为已解决,如果很快没有其他优化代码的答案,例如使用循环或其他东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-26
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2011-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      相关资源
      最近更新 更多