SQL SELECT顺序由2列和group by组成

时间:2009-09-12 02:54:04

标签: sql mysql group-by sql-order-by

以下是RS返回和发布的SQL,

SELECT *, (UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time)) AS T
 FROM games
WHERE game_status > 10
ORDER BY status, T;


game_id, player_id, start_time, end_time, score, game_status, is_enabled, T
65, 22, '2009-09-11 17:50:35', '2009-09-11 18:03:07', 17, 11, 1, 752
73, 18, '2009-09-11 18:55:07', '2009-09-11 19:09:07', 30, 11, 1, 840
68, 20, '2009-09-11 18:03:08', '2009-09-11 18:21:52', 48, 11, 1, 1124
35, 18, '2009-09-11 15:46:05', '2009-09-11 16:25:10', 80, 11, 1, 2345
13, 8, '2009-09-11 12:33:31', '2009-09-11 15:21:11', 40, 11, 1, 10060
11, 5, '2009-09-11 12:22:34', '2009-09-11 15:21:42', 55, 11, 1, 10748
34, 17, '2009-09-11 15:45:43', '2009-09-11 21:00:45', 49, 11, 1, 18902
2, 1, '2009-09-10 20:46:59', '2009-09-11 23:45:21', 3, 11, 1, 97102
84, 1, '2009-09-11 23:51:29', '2009-09-11 23:51:42', 10, 12, 1, 13

我想通过player_id分组,(即每个Player_id得到最好的结果,它取决于“game_status - min”,以及时间T,

所以我添加了一个group by子句,但它没有返回min

SELECT *, (UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time)) AS T
 FROM games
WHERE game_status > 10
GROUP BY player_id
ORDER BY game_status, T;

35, 18, '2009-09-11 15:46:05', '2009-09-11 16:25:10', 80, 11, 1, 2345
13, 8, '2009-09-11 12:33:31', '2009-09-11 15:21:11', 40, 11, 1, 10060
34, 17, '2009-09-11 15:45:43', '2009-09-11 21:00:45', 49, 11, 1, 18902
1, 1, '2009-09-10 20:39:44', '2009-09-10 20:41:21', 10, 12, 1, 97
24, 12, '2009-09-11 14:46:06', '2009-09-11 14:53:30', 10, 12, 1, 444
5, 3, '2009-09-11 10:56:22', '2009-09-11 11:13:01', 11, 12, 1, 999
37, 20, '2009-09-11 15:51:13', '2009-09-11 16:15:04', 14, 12, 1, 1431
79, 31, '2009-09-11 20:34:17', '2009-09-11 20:43:29', 4, 13, 1, 552
18, 9, '2009-09-11 13:09:47', '2009-09-11 18:33:10', 2, 13, 1, 19403
72, 30, '2009-09-11 18:46:29', '2009-09-11 18:48:44', 0, 14, 1, 135
40, 22, '2009-09-11 16:12:39', '2009-09-11 16:18:23', 3, 14, 1, 344
8, 5, '2009-09-11 12:15:54', '2009-09-11 12:21:48', 25, 14, 1, 354
85, 33, '2009-09-12 01:14:01', '2009-09-12 01:20:43', 0, 14, 1, 402
22, 11, '2009-09-11 13:50:41', '2009-09-11 13:57:24', 7, 14, 1, 403


SELECT *, min(UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time)) AS T
 FROM games
WHERE game_status > 10
GROUP BY player_id
ORDER BY game_status, T;

如果我选择min(T),它不会返回最小行,而是保留保留列上的最小值。

我搜索了一些自我加入的方法,比如http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

子查询SELECT for min(),但我不能在两列上发出两个min(),因为它不会返回我想要的特定行。

select type, min(price) as minprice
from fruits
group by type;

我希望有一种方法可以作为第一个SQL的过滤器来删除重复的player_id行。

4 个答案:

答案 0 :(得分:2)

根据我的收集情况,您希望查看给定game_statusplayer_id组合的最高game_id的最短时间。试试这个:

select
    g1.game_id,
    g1.player_id,
    min(UNIX_TIMESTAMP(g1.end_time) - UNIX_TIMESTAMP(g1.start_time)) as t,
    g1.game_status
from
    games g1
    inner join (select game_id, player_id, max(game_status) as max_status 
                from games where game_status > 10) g2 on
        g1.game_id = g2.game_id
        and g1.player_id = g2.player_id
        and g1.game_status = g2.max_status
group by
    g1.game_id,
    g1.player_id,
    g1.game_status
order by
    g1.player_id,
    g1.game_id,
    g1.game_status,
    T

答案 1 :(得分:0)

看起来你错过了MIN功能,并且对你的过滤条款稍有改动。

如:

SELECT *, MIN(UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time)) AS T 
FROM games 
GROUP BY player_id 
HAVING MIN(UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time)) > 10
ORDER BY game_status, T;

我移动了“> 10”逻辑,因为我相信你的意图是过滤掉那些最佳游戏状态低于10的玩家。这与筛选出小于10的单个游戏状态条目(这是您通过WHERE子句进行的操作)不同。

试一试。看起来你正在使用MySQL,这不是我熟悉的数据库系统。

答案 2 :(得分:0)

我对你的问题中的一些短语有点不确定,但你需要按照以下几行进行嵌套的SELECT操作:

SELECT g.*
  FROM (SELECT *,
               (UNIX_TIMESTAMP(g.end_time) - UNIX_TIMESTAMP(g.start_time)) AS t
          FROM games
       ) AS g
       JOIN (SELECT player_id,
                    MIN(UNIX_TIMESTAMP(end_time) -
                        UNIX_TIMESTAMP(start_time)) AS min_t
               FROM games
              WHERE game_status > 10
              GROUP BY player_id
             ) AS r
      ON g.player_id = r.player_id AND g.t = r.min_t
ORDER BY game_status, g.t;

'r'查询返回玩家ID以及该玩家的相应最短时间;与主表连接,以相同的最短时间获取该播放器的所有行。通常,这将是一个条目,但如果某人有两个同时具有的游戏,则查询将同时返回。

我不清楚是否有另一种消除结果集歧义的方法;可能有。

答案 3 :(得分:0)

感谢您的回复。

我正在寻找Eric和Jonathan的解决方案。

让我详细解释一下。

正如Eric所说,我正在寻找game_status和min time(T)的结果, 我只需要状态> 10,排名较小, (即11> 12> 13> 14,只有四个状态)并从他们的时间确定。

我从表中选择了前5行player_id = 18:

SELECT *,(UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP(start_time))AS T 从game_id = 18的游戏中,game_status,T;

game_id, player_id, start_time, end_time, score, game_status, is_enabled, T
73, 18, '2009-09-11 18:55:07', '2009-09-11 19:09:07', 30, 11, 1, 840
35, 18, '2009-09-11 15:46:05', '2009-09-11 16:25:10', 80, 11, 1, 2345
53, 18, '2009-09-11 16:57:30', '2009-09-11 16:58:28', 0, 14, 1, 58
59, 18, '2009-09-11 17:27:42', '2009-09-11 17:28:51', 0, 14, 1, 69
57, 18, '2009-09-11 17:24:25', '2009-09-11 17:25:41', 0, 14, 1, 76

玩家18玩了很多次游戏。他得到了不同的结果(game_status)。 现在,我们正在为每个球员取得最好的结果。

显然,18的最佳结果是

73, 18, '2009-09-11 18:55:07', '2009-09-11 19:09:07', 30, 11, 1, 840

状态为11,时间为840.

请注意,他拍摄的最佳时间是game_id = 53(上面的第3行),我们不会将此结果视为状态为14.因此,使用min(UnixTimeSTAMP ...)将无济于事结果集为58。