PostgreSQL: что не так с first_value (unique_column) OVER ()? - PullRequest
0 голосов
/ 07 сентября 2018

В соответствии с PostgreSQL: обнаружив первые / последние строки набора результатов , у меня были основания подозревать, что такое предложение опасно или иным образом неуместно, и я хочу лучше это понять. Возьмите:

SELECT last_value(unique_column) OVER (), * FROM mytable;

unique_column является уникальным и не нулевым. Так что же не так с использованием OVER () таким образом? Это опасно / ненадежно? Субоптимальное? Из того, что я могу сказать, это должно возвращать значение из последней строки в наборе результатов - по крайней мере, так оно и было, когда я его пробовал. Мне сказали, что «последний» не имеет смысла без сортировки, но ясно, что есть последняя строка, которая возвращается. Мне также сказали, что OVER () означает «все идет», что говорит о том, что результаты ненадежны, но до сих пор, каждый раз, когда я выполнял такой запрос, мне последовательно давали значение с конца из набора результатов.

Теперь я обнаружил проблему при использовании ORDER BY:

SELECT last_value(unique_column) OVER (), * FROM mytable ORDER BY something_else;

Но мое решение для этого - подзапрос:

SELECT last_value(unique_column) OVER (), * FROM (SELECT * FROM mytable ORDER BY something_else) sub;

Это как если бы OVER () означает, что аналитические функции (такие как first_value() и last_value()) работают в соответствии с порядком, в котором происходит двигатель, читая таблицу / подзапрос. И, насколько я могу судить, у вас достаточно контроля над порядком, в котором движок читает таблицу / подзапрос (без необходимости выполнять ненужную сортировку).

Я использую PostgreSQL 9.6 в среде Debian 9.5.

Ответы [ 2 ]

0 голосов
/ 22 декабря 2018

Я должен отметить, что в последние несколько месяцев это решение работало довольно хорошо, и мне не показали альтернативы, поэтому я собираюсь продолжать его использовать. Тем не менее, я должен отметить, что он привередлив и может потерпеть неудачу, если вы внесете определенные изменения и не будете принимать во внимание аналитику. (Без сомнения, я неправильно использую эту функцию, и она была не разработана для этой цели). Поэтому я буду использовать это место для записи ошибок, когда нахожу их.

  1. Если вы заказываете свои результаты, у вас есть проблема, но я уже объяснил это в вопросе.
  2. Я пытался использовать его во внешнем соединении. Поскольку это привело к тому, что поля в результирующем наборе были нулевыми (даже если они были взяты из полей в таблице, которые не могут быть нулевыми), это заставило OVER() вернуть NULL. У меня есть несколько идей о том, как обойти это, но они сделали бы запрос очень уродливым и, возможно, очень неэффективным.
0 голосов
/ 07 сентября 2018

Вы должны предоставить ORDER BY внутри OVER предложение:

SELECT *,
 last_value(unique_column) 
 OVER (ORDER BY sth_else ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM mytable
...