如何根据多个排序列选择每组的顶行?

ran*_*its 7 mysql sql select group-by aggregate-functions

我有一个如下所示的查询:

SELECT time_start, some_count
    FROM foo
    WHERE user_id = 1
    AND DATE(time_start) = '2016-07-27'
    ORDER BY some_count DESC, time_start DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

这样做会让我返回一行,其中some_count是最高计数user_id = 1.这也给我的时间戳这对于最新的some_count,因为some_count可能是多个相同time_start的价值观和我想要的最新一个.

现在我要做的就是运行一个查询user_id,在这种情况下,对于特定日期至少发生过一次的每一个单元都会计算出来2016-07-27.最终它可能需要GROUP BY,因为我正在寻找每组的最大值user_id

编写这种性质的查询的最佳方法是什么?

100*_*111 2

我正在分享我的两种方法。

方法#1(可扩展):

使用MySQL user_defined variables

SELECT
    t.user_id,
    t.time_start,
    t.time_stop,
    t.some_count
FROM 
(
    SELECT
        user_id,
        time_start,
        time_stop,
        some_count,
        IF(@sameUser = user_id, @rn := @rn + 1,
             IF(@sameUser := user_id, @rn := 1, @rn := 1)
        ) AS row_number

    FROM    foo
    CROSS JOIN (
        SELECT
            @sameUser := - 1,
            @rn := 1
    ) var
    WHERE   DATE(time_start) = '2016-07-27'
    ORDER BY    user_id,    some_count DESC,    time_stop DESC
) AS t
WHERE t.row_number <= 1
ORDER BY t.user_id;
Run Code Online (Sandbox Code Playgroud)

可扩展,因为如果您想要每个用户最新的 n 行,那么您只需要更改此行:

... WHERE t.row_number <= n...

如果查询提供了预期结果,我可以稍后添加解释


方法#2:(不可扩展)

使用INNER JOIN and GROUP BY

SELECT 
 F.user_id,
 F.some_count,
 F.time_start,
 MAX(F.time_stop) AS max_time_stop
FROM foo F
INNER JOIN 
(
    SELECT 
        user_id,
        MAX(some_count) AS max_some_count
    FROM foo
    WHERE DATE(time_start) = '2016-07-27'
    GROUP BY user_id
) AS t
ON F.user_id = t.user_id AND F.some_count = t.max_some_count
WHERE DATE(time_start) = '2016-07-27'
GROUP BY F.user_id
Run Code Online (Sandbox Code Playgroud)