关于sql:返回GROUP BY查询中的多个列

Return multiple columns in a GROUP BY query

本问题已经有最佳答案,请猛点这里访问。

请考虑下表:

1
2
3
4
5
6
7
8
9
10
11
    tbl_start_times

    id mach_id start_time
    -- ------- ----------
    1  1       00:12
    2  3       05:18
    3  1       03:56
    4  2       01:51
    5  1       12:48
    6  2       00:10
    7  3       09:15

我想为每个mach_id返回id,mach_id和MIN(start_time)。

代码:

1
    SELECT mach_id, MIN(start_time) FROM tbl_start_times GROUP BY mach_id

返回此结果:

1
2
3
4
5
    mach_id start_time
    ------- ----------
    1       00:12
    3       05:18
    2       00:10

如何将ID添加到我的结果中以便获得此结果?

1
2
3
4
5
    id mach_id start_time
    -- ------- ----------
    1  1       00:12
    2  3       05:18
    6  2       00:10


在Postgres中有两种方法可以做到这一点:

使用Postgres特定的distinct on ()运算符:

1
2
3
SELECT DISTINCT ON (match_id) id, match_id, start_time
FROM tbl_start_times
ORDER BY match_id, start_time;

或者使用窗口功能:

1
2
3
4
5
6
7
8
WITH numbered_times AS (
    SELECT id, match_id, start_time,
           ROW_NUMBER() OVER (partition BY match_id ORDER BY start_time) AS rn
    FROM tbl_start_times
)
SELECT id, match_id, start_time
FROM numbered_times
WHERE rn = 1;

当您使用distinct(或最小/最大解决方案)时,这也可以让您轻松选择"第二"或"第四"行,而不仅仅是"第一"或"最后"行

如果多行是"最低"(即,对于相同的match_id具有相同的最低时间)并且您想要查看所有行,请使用dense_rank()而不是row_number()

具有distinct on的解决方案通常比使用窗口函数的相应解决方案更快。窗口函数是标准的SQL,然后在(几乎)所有现代DBMS上运行。两个版本通常比使用子查询或派生表的解决方案更快,因为只需要一次传递来读取数据。

SQLFiddle示例:http://sqlfiddle.com/#!12/caa95/5


您可以使用相关子查询执行此操作,如下所示:

1
2
3
4
5
6
SELECT id, mach_id, start_time
FROM tbl_start_times tst
WHERE start_time = (SELECT MIN(START TIME)
                    FROM tbl_start_times tst2
                    WHERE tst2.mach_id = tst.mach_id)
ORDER BY id

SQL小提琴


试试这个:

1
2
3
4
5
6
SELECT t.id , t.mach_id, t.start_time
FROM tbl_start_times t,
    (SELECT mach_id, MIN(start_time) AS start_time
    FROM tbl_start_times
    GROUP BY mach_id) t1
WHERE t.mach_id=t1.mach_id AND t.start_time=t1.start_time