SELECT * и SELECT column возвращает строки в разном порядке
Есть запрос №1:
WITH cte1 AS
(SELECT *,
ROW_NUMBER() OVER (ORDER BY column1) AS rn
FROM table)
SELECT column0
FROM cte1
WHERE rn = 1022;
есть запрос №2:
WITH cte1 AS
(SELECT column0,
ROW_NUMBER() OVER (ORDER BY column1) AS rn
FROM table)
SELECT column0
FROM cte1
WHERE rn = 1022;
PostgreSQL, в column0 нет NULL-ов, значения уникальны.
Но, почему то, при SELECT * и SELECT column0 в итоге я получаю разные значения на rn 1022 (не только на 1022, это просто для примера). Сортировка в cte1 одна и та же, ничего не меняется, кроме количества колонок. Эта какая-то особенность SQL или с чем может быть связано?
Ответы (2 шт):
Да, это особенность SQL. Если у вас явно не указана сортировка, то база данных может вернуть строки в любом порядке. Как ей захочется. И это может зависить не только от звездочки в запросе, но и просто от времени когда делается запрос.
Хотите избежать неоднозначности - указывайте сортировку в явном виде.
Проблема возникает из-за того, что сортировка по column1 в вашем случае неоднозначна т.е. в этом поле есть дубликаты и отсортировать по column1 можно разными способами, что БД и делает при разных запросах.
Вот пример:
column0 | column1
--------+---------
A | 1
B | 1
Если выполнить запрос из CTE, до любой порядок строк будет правильным и если вы будете выбирать, скажем, rn=1 то вы можете получить в результате и A и B.
Чтоб этого избежать нужно задавать сортировку по полям, которые однозначно задают порядок. Обычно достаточно включить последним (т.е. самым низкоприоритетным) полем в сортировке уникальное поле (например, первичный ключ), что-то вроде такого:
SELECT column0,
ROW_NUMBER() OVER (ORDER BY column1, id) AS rn
FROM table
В этом случае порядок всегда будет определен однозначно, т.к. для записей с одинаковыми значениями column1 сортировка будет происходить по полю id.