SQL ВЫБРАТЬ порядок по 2 столбцам и сгруппировать по - PullRequest
2 голосов
/ 12 сентября 2009

Вот возврат 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), он не возвращает строку min, а значение min в столбце hold.

Я искал какой-то метод с самообъединением, скажем, http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

Подзапрос SELECT для min (), но я не могу выдать два min () для двух столбцов, поскольку он не возвращает конкретные строки, которые я хочу.

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

Я надеюсь, что в качестве первого фильтра SQL можно удалить дублированные строки player_id.

Ответы [ 4 ]

2 голосов
/ 12 сентября 2009

Из того, что я могу собрать, вы хотите увидеть, какое минимальное время было на самом высоком game_status для данной комбинации player_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
0 голосов
/ 12 сентября 2009

Спасибо за ответы.

Я ищу решение Эрика и Джонатана.

Позвольте мне объяснить подробно.

Как уже упоминал Эрик, я ищу результат из game_status и min time (T), Мне нужен только статус> 10, и рейтинг от меньшего, (т.е. 11> 12> 13> 14, только четыре статуса) и определите по их времени.

Я взял 5 верхних строк player_id = 18 из таблицы:

SELECT *, (UNIX_TIMESTAMP (конечное время) - UNIX_TIMESTAMP (начальное время)) AS T ОТ игр, где player_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 как набор результатов.

0 голосов
/ 12 сентября 2009

Я немного не уверен относительно некоторых фраз в вашем вопросе, но вам нужно выполнить вложенную операцию 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' возвращает идентификатор игрока исоответствующее минимальное время для этого игрока;он соединяется с основной таблицей, извлекающей все строки для этого игрока с одинаковым минимальным временем.Как правило, это будет одна запись, но если у кого-то есть две игры с одинаковым временем, запрос будет возвращать обе.может быть.

0 голосов
/ 12 сентября 2009

Похоже, вам не хватает функции 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», потому что я считаю, что вы хотите отфильтровать тех игроков, чей лучший игровой статус меньше десяти. Это другой критерий, нежели отфильтровывание каких-либо отдельных записей о состоянии игры, которые меньше десяти (это то, что вы делали с помощью предложения WHERE).

Попробуйте. Похоже, вы используете MySQL, который не является системой баз данных, с которой я хорошо знаком.

...