Laravel - 查询构建器以选择具有唯一列值的多行(具有另一列的最大值)

Posted

技术标签:

【中文标题】Laravel - 查询构建器以选择具有唯一列值的多行(具有另一列的最大值)【英文标题】:Laravel - query builder to select multiple rows with unique column value (which has max value from another column) 【发布时间】:2016-06-17 11:35:38 【问题描述】:

我有一张这样的桌子

data | usage_date | usage_hour
x    | 03/03/2016 | 05:30:30
y    | 03/02/2016 | 11:30:30
z    | 03/03/2016 | 07:30:30
p    | 03/02/2016 | 05:30:30

当我运行 Laravel 查询时,我希望看到以下行被选中

y    | 03/02/2016 | 11:30:30
z    | 03/03/2016 | 07:30:30

所以基本上我想构建一个查询,它将为“usage_date”提供唯一值,最大“usage_hour”。如何构建此查询?

【问题讨论】:

我尝试使用 ->max('usage_hour') 但失败并出现分组错误:7 【参考方案1】:

首先,你需要知道如何在纯 SQL 中做到这一点,因为 Laravel 的 QueryBuilder 只是一个构建 SQL 查询的工具。

您描述的任务有点棘手,不幸的是,没有简短的 SQL 查询可以解决这个问题。

可以用window functions:

SELECT DISTINCT usage_date, 
    first_value(usage_hour) OVER (PARTITION BY usage_date ORDER BY usage_hour DESC) as usage_hour, 
    first_value(data) OVER (PARTITION BY usage_date ORDER BY usage_date DESC, usage_hour DESC) as data
FROM t

(sqlfiddle example)

使用 QueryBuilder 将如下所示:

DB::table('t')
    ->distinct()
    ->select([
        'usage_date',
        DB::raw('first_value(usage_hour) OVER (PARTITION BY usage_date ORDER BY usage_hour DESC) as usage_hour'),
        DB::raw('first_value(data) OVER (PARTITION BY usage_date ORDER BY usage_date DESC, usage_hour DESC) as data')
    ])
    ->get()

或者可以通过子查询来完成(效率低且不酷):

SELECT usage_date, max(usage_hour) as usage_hour,
  (SELECT data FROM t AS t2 
   WHERE t2.usage_date = t.usage_date AND t2.usage_hour = max(t.usage_hour) 
  LIMIT 1) AS data
FROM t
GROUP BY usage_date

如果有人知道没有子查询和窗口函数的方法,请告诉我。

【讨论】:

【参考方案2】:

试试这个,看看效果如何

$table = \DB::table('table name')->distinct('usage_date')->groupBy('usage_date')->orderBy('usage_hour','desc')->get();

【讨论】:

错了。会产生错误ERROR: column "table_name.data" must appear in the GROUP BY clause or be used in an aggregate function 那我猜你使用的是 mysql 5.7。它的 sql_mode 更严格。它可以在我的机器上运行。我已经改变了我的 sql_mode。 其实我们说的是postgresql。但是我在sqlfiddle 中检查了您的查询,它产生了错误的结果。 sqlfiddle.com/#!2/bb0ae/1 哦,好的。从来不知道它是 postgresql。 我的意思是即使mysql,您的查询也不正确。检查我之前给出的 sqlfiddle 链接。

以上是关于Laravel - 查询构建器以选择具有唯一列值的多行(具有另一列的最大值)的主要内容,如果未能解决你的问题,请参考以下文章

laravel 基于另一列值的唯一验证规则

使用名为查询的数据 jpa 返回具有不同列值的行

Laravel 查询,其中列值大于相关模型列值的总和

通过具有最大列值的记录过滤 Django 查询

SQL 查询以查找具有相同列值的多行

需要帮助修复 Oracle SQL 查询以返回具有最大列值的行