СУБД Sybase
В моей таблице игроков есть 4 столбца:
Если я хочу найти счет игрока, где post_dt - максимальное значение, а add_dt - максимальное значение этого post_dt и этого игрока, как мне это сделать? Мой запрос ниже занимает очень много времени и, вероятно, не очень эффективен.
select player, score from tb t1
where post_dt in
(select max(add_dt)
from tb t2
where t1.player = t2.player and t2.post_dt in
(select max(post_dt)
from tb t2
where t1.player = t2.player))
Таблица
PLAYER SCORE POST_DT ADD_DT
001 15 2017-02-01 2017-01-15
001 26 2017-02-01 2017-01-17
001 31 2017-01-28 2017-01-10
002 4 2017-03-25 2017-02-25
002 14 2017-03-25 2017-02-13
002 27 2017-03-25 2017-03-05
003 31 2017-01-02 2016-12-25
003 4 2017-01-03 2016-12-25
Ожидаемые результаты запроса:
01, 26, 2017-02-01, 2017-01-17
02, 27, 2017-03-25, 2017-03-05
03, 4, 2017-01-03, 2016-12-25
Можете ли вы немного его уточнить, желательно с некоторыми примерами данных. Трудно понять ваше требование.
какой продукт Sybase RDBMS (ASE? SQLAnywhere? IQ? Advantage?) и версия? в дополнение к комментарию Цетина прочтите Как создать минимальный, полный и проверяемый пример, затем вернитесь и обновите свой вопрос
Я обновил свой пост образцами данных.
Вы можете добиться этого, используя коррелированные подзапросы.
SELECT t1.player,
t1.score
FROM tb t1
WHERE t1.post_dt = (SELECT max(t2.post_dt)
FROM tb t2
WHERE t2.player = t1.player)
AND t1.add_dt = (SELECT max(t2.add_dt)
FROM tb t2
WHERE t2.player = t1.player
AND t2.post_dt = t1.post_dt);
Или, если ваша СУБД поддерживает оконные функции, используйте оконную функцию rank()
.
SELECT x.player,
x.score
FROM (SELECT t.player,
t.score,
rank() OVER (PARTITION BY t.player
ORDER BY t.post_dt DESC,
t.add_dt DESC) r
FROM tb t) x
WHERE x.r = 1;
Еще один вариант - внутреннее объединение подзапросов, которые создают максимумы по player
или player
и post_dt
соответственно.
SELECT t1.player,
t1.score
FROM tb t1
INNER JOIN (SELECT t2.player,
max(t2.post_dt) post_dt
FROM tb t2
GROUP BY t2.player) t3
ON t3.player = t1.player
AND t3.post_dt = t1.post_dt
INNER JOIN (SELECT t3.player,
t3.post_dt,
max(t3.add_dt) add_dt
FROM tb t3
GROUP BY t3.player,
t3.post_dt) t4
ON t4.player = t1.player
AND t4.post_dt = t1.post_dt
AND t4.add_dt = t1.add_dt;
Это здорово! Спасибо. Я использовал ваше второе решение.
Какая у вас база данных?