SQL group by:选择另一列有其最小值/最大值的值

Posted

技术标签:

【中文标题】SQL group by:选择另一列有其最小值/最大值的值【英文标题】:SQL group by: select value where another column has its min/max 【发布时间】:2017-09-05 07:37:12 【问题描述】:

我想按一列分组,获取第二列的最小值和最大值,并且(这是棘手的部分!)从第三列中获取值,其中第二列在组中具有最小值。

例子:

我的表:

ID     TS     GRP
==================
 1     20      A
 2     20      B
 3     10      A
 4     30      A
 5     10      B
 6     40      A

期望的结果(ID 应该是 TS 最小的记录中的值):

ID    MIN_TS   MAX_TS   GRP
============================
 3      10       40      A
 5      10       20      B

总的来说,分组查询很简单:

SELECT <???> AS ID, MIN(TS) AS MIN_TS, MAX(TS) AS MAX_TS, GRP
FROM MyTable
GROUP BY GRP

但是 ID 部分呢?它不适用于分组,对吗?但为什么?最好的解决方法是什么?

【问题讨论】:

您需要 JOIN 才能找到该行。 出现平局怎么办?或者它们不能发生(即您对 TS + GRP 有独特的约束)? 你是对的,这就是为什么它不适用于分组的原因...... 【参考方案1】:

在子查询中进行聚合,然后在另一个子查询中查找每个组的 ID:

SELECT
  (SELECT TOP(1) id FROM MyTable WHERE grp = agg.grp ORDER BY ts DESC) AS id,
  min_ts, max_ts, grp
FROM (SELECT min(ts) AS min_ts, max(ts) AS max_ts, grp
      FROM MyTable
      GROUP BY grp) agg

或者使用窗口函数:

SELECT id, min_ts, max_ts, grp
FROM (SELECT 
        id,
        min(ts) OVER (PARTITION BY grp) min_ts,
        max(ts) OVER (PARTITION BY grp) max_ts,
        grp,
        row_number OVER (PARTITION BY grp ORDER BY ts) rn
      FROM MyTable)
WHERE rn = 1;

此查询使用窗口函数计算每个组的min_tsmax_ts,然后过滤以仅包含每个组的第一行(按ts 排序)。

【讨论】:

我更喜欢使用窗口函数的第二种解决方案。 请注意,排名函数在非常大的数据集上非常慢。

以上是关于SQL group by:选择另一列有其最小值/最大值的值的主要内容,如果未能解决你的问题,请参考以下文章

如果另一列有重复值,sql查询用相同的值替换列

SQL Server 2012 中的 group_concat 与 ORDER BY 另一列

如何根据MySQL中的另一列有条件地选择列

按 Sql Server 中的一列分组并按未包含在聚合函数或 GROUP BY 子句中的另一列排序

sql一列有多值查询,根据多个只查询我想要的数据

应用 group_by 并汇总数据,同时保留所有列的信息