Pull to refresh
32
0
Евгений Бредня @bzq

IT

Send message
Добавил это решение в статью (:
Где ж Вы раньше были? (:
Не-не. Все нужные значения считаются в один проход, включая все вычисляемые значения. Оконные (и аналитические) функции работают весьма эффективно, даже самописные. Вот тут можно посмотреть на внутреннюю кухню таких функций: habr.com/ru/company/postgrespro/blog/351008
Да, совершенно верно. И даже решение такого плана было представлено вот тут в комментариях к предыдущей статье.
Оконные функции считаются в один проход, так что третий способ самый быстрый. Второй тоже быстрый, но «капризный». А первый способ в таких условиях будет страшно медленным, чем больше набор данных, тем медленнее.

ЗЫ Позвали бесплатно на конференцию
На мой вкус, для собеседования это плохая задача, слишком сложная.
Для тех, кто отслеживает именно комментарии, опубликовал разбор задачи: habr.com/ru/company/postgrespro/blog/557300
Да, пора бы… (:
Вроде затихло, видимо желающие отписались, а остальным некогда или стесняются.

Впрочем, тема была раскрыта достаточно полно. Буду писать следующую статью с объяснением, как решать эту задачу и разбором предложенных вариантов.
Да, можно. И подобное решение уже приводили. В JSON зато можно положить все значения, а не только какое-то одно.
Спасибо за вариант, он почти работающий. На такую ошибку я уже указывал в комментариях выше, нужно указать ROWS… в определение окна, где sum().
Да хотя бы явно преобразовывать дату в строку по маске, чтобы знать сколько потом откусывать. Тут предложили ещё аналогичный вариант с преобразованием в JSON. Для постгреса так, наверное, даже проще.
Да, такого не было. И почти работает! DISTINCT даёт себя знать, дубликаты строк пропадают. Не знаю, нужны ли они будут или нет, но пропадают… А так красиво, конечно.
Анекдот в тему. Встречаются два девопса. Один другому:
— Мне бы CI и деплой на сервер настроить надо…
— Давай я тебе объясню, как это сделать!
— Объяснить я и сам могу. Мне бы сделать…
Работает. Действительно, можно было обойтись чем-то одним из двух — или оконными функциями, или JOIN-ом. Потому и несколько тяжеловесно.
Так как такое поведение не определено, то и неважно. Главное, чтобы при этом запрос что-то выбирал, а не падал с ошибками.

Вот исходя из того, что с одной датой может быть много строчек, мне больше нравится вариант с 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… и без на таких данных:
(1,1,'2000-01-05','P', 90.0, 0, 0),
(1,1,'2000-01-06','P', 80.0, 0, 0),
(1,1,'2000-01-06','R',120.0,41.22,6.19),
(1,1,'2000-01-07','P', 80.0, 0, 0),

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Works in
Date of birth
Registered
Activity