Не-не. Все нужные значения считаются в один проход, включая все вычисляемые значения. Оконные (и аналитические) функции работают весьма эффективно, даже самописные. Вот тут можно посмотреть на внутреннюю кухню таких функций: habr.com/ru/company/postgrespro/blog/351008
Оконные функции считаются в один проход, так что третий способ самый быстрый. Второй тоже быстрый, но «капризный». А первый способ в таких условиях будет страшно медленным, чем больше набор данных, тем медленнее.
Да хотя бы явно преобразовывать дату в строку по маске, чтобы знать сколько потом откусывать. Тут предложили ещё аналогичный вариант с преобразованием в JSON. Для постгреса так, наверное, даже проще.
Да, такого не было. И почти работает! DISTINCT даёт себя знать, дубликаты строк пропадают. Не знаю, нужны ли они будут или нет, но пропадают… А так красиво, конечно.
Анекдот в тему. Встречаются два девопса. Один другому:
— Мне бы CI и деплой на сервер настроить надо…
— Давай я тебе объясню, как это сделать!
— Объяснить я и сам могу. Мне бы сделать…
Так как такое поведение не определено, то и неважно. Главное, чтобы при этом запрос что-то выбирал, а не падал с ошибками.
Вот исходя из того, что с одной датой может быть много строчек, мне больше нравится вариант с ROWS, он будет переключать уровень стоимости на новый при каждой встреченной R-строке. Алгоритмы СУБД часто не перемешивают уже упорядоченные в наборе записи, сохраняя оригинальный порядок, так что цены будут расставлены наиболее ожидаемым образом.
Разное поведение, потому что разные вещи выражает. OVER w — это запуск оконной функции в окне w, которое можно определить отдельно. А если OVER (w), то это уже выражение, которое может быть задано в том числе с использованием существующего окна w. В документации достаточно хорошо видна разница: postgrespro.ru/docs/postgresql/12/sql-expressions#SYNTAX-WINDOW-FUNCTIONS
(array_agg(start_date) FILTER(WHERE kind = 'R') OVER w)[1]
...
WINDOW
w AS (PARTITION BY stock_id, prod_id ORDER BY start_date DESC
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
О! Я бы назвал такую реализацию классической. Сперва делаем группы по уровням стоимости, потом оконной функцией вытаскиваем значения.
Но в реализации есть ошибка. Надо или явно указать порядок по kind, чтобы первой строкой по каждой дате всегда была R, или в определении рамки указать явно ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, чтобы s увеличивалась только на R-строках, а не на родственных. По умолчанию используется режим RANGE. Попробуйте запустить запрос с ROWS… и без на таких данных:
ЗЫ Позвали бесплатно на конференцию
Впрочем, тема была раскрыта достаточно полно. Буду писать следующую статью с объяснением, как решать эту задачу и разбором предложенных вариантов.
— Мне бы CI и деплой на сервер настроить надо…
— Давай я тебе объясню, как это сделать!
— Объяснить я и сам могу. Мне бы сделать…
Вот исходя из того, что с одной датой может быть много строчек, мне больше нравится вариант с ROWS, он будет переключать уровень стоимости на новый при каждой встреченной R-строке. Алгоритмы СУБД часто не перемешивают уже упорядоченные в наборе записи, сохраняя оригинальный порядок, так что цены будут расставлены наиболее ожидаемым образом.
Разное поведение, потому что разные вещи выражает. OVER w — это запуск оконной функции в окне w, которое можно определить отдельно. А если OVER (w), то это уже выражение, которое может быть задано в том числе с использованием существующего окна w. В документации достаточно хорошо видна разница: postgrespro.ru/docs/postgresql/12/sql-expressions#SYNTAX-WINDOW-FUNCTIONS
Но в реализации есть ошибка. Надо или явно указать порядок по kind, чтобы первой строкой по каждой дате всегда была R, или в определении рамки указать явно ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, чтобы s увеличивалась только на R-строках, а не на родственных. По умолчанию используется режим RANGE. Попробуйте запустить запрос с ROWS… и без на таких данных: