#sql #postgresql
Вопрос:
Я использую базу данных PostgreSQL (12.8).
Учитывая events
сортировку по start_time
, я хотел бы получить следующие 10
события после события с id = 10
помощью .
Моя первая идея была примерно такой:
SELECT *
FROM events
ORDER BY start_time
WHERE id > 10
LIMIT 10;
Однако это не работает, потому WHERE
что предложение-всегда применяется перед ORDER BY
предложением -. Другими словами, сначала выбираются все события , у которых есть an id > 10
, и только оставшиеся события затем упорядочиваются по start_time
.
Затем я придумал выражение CTE. Если запись с идентификатором 10
имеет row_number
3
:
WITH ordered_events AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY start_time DESC) AS row_number
FROM events
)
SELECT *
FROM ordered_events
WHERE row_number > 3
LIMIT 10;
Это работает так, как хотелось бы, если бы я знал об row_number
этом заранее. Однако я знаю только идентификатор, id = 10
т. Е.
а) В идеале я бы сделал что-то подобное (однако я не знаю, есть ли какой-либо способ написать такое выражение):
WITH ordered_events AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY start_time DESC) AS row_number
FROM events
)
SELECT *
FROM ordered_events
WHERE row_number > (row_number of row where the ID is 10) # <------
LIMIT 10;
б) Единственная альтернатива, которую я придумал, — это сначала получить row_number
данные для всех записей, а затем выполнить второй запрос.
Первый запрос:
SELECT id, ROW_NUMBER() OVER (ORDER BY start_time DESC) AS row_number
FROM events;
Теперь я знаю, что row_number
для записи с идентификатором 10
есть 3
. Таким образом, у меня достаточно информации, чтобы выполнить запрос с выражением CTE, как описано выше. Однако производительность низкая, потому что мне нужно извлечь все записи из events
первого запроса.
Я был бы очень признателен, если бы вы помогли мне найти (эффективный) способ сделать это.
Комментарии:
1. «…потому что предложение WHERE всегда применяется перед предложением ORDER BY…»-неверно. Ядра баз данных выполняют запрос, используя внутренние стратегии. То, о чем вы говорите, вероятно, преподается как педагогический инструмент, но реальные рабочие механизмы так не работают.
Ответ №1:
Вам нужны только строки со временем начала меньше, чем время начала идентификатора 10. Используйте WHERE
для этого предложение.
select *
from events where start_time < (select start_time from events where id = 10)
order by start_time desc
limit 10;
Этот запрос может извлечь выгоду из индекса start_time. (Я считаю само собой разумеющимся, что уже существует индекс ID, позволяющий быстро найти строку с идентификатором 10.)