Фильтрация по оконной функции приводит к Postgresql
ОК, первоначально это была просто шутка, которую мы имели с моим другом, но она превратилась в интересный технический вопрос:)
у меня есть следующие stuff
стол:
CREATE TABLE stuff
(
id serial PRIMARY KEY,
volume integer NOT NULL DEFAULT 0,
priority smallint NOT NULL DEFAULT 0,
);
таблица содержит записи для всех моих вещей, с соответствующим объемом и приоритетом (сколько мне нужно).
у меня есть сумка с указанным объемом, скажем 1000
. Я хочу выбрать из таблицы все вещи, которые я могу положить в сумку, упаковывая самые важные вещи первый.
это похоже на случай использования оконных функций, поэтому вот запрос, который я придумал:
select s.*, sum(volume) OVER previous_rows as total
from stuff s
where total < 1000
WINDOW previous_rows as
(ORDER BY priority desc ROWS between UNBOUNDED PRECEDING and CURRENT ROW)
order by priority desc
проблема с ним, однако, в том, что Postgres жалуется:
ERROR: column "total" does not exist
LINE 3: where total < 1000
если я удалю этот фильтр, общий столбец будет правильно рассчитан, результаты будут правильно отсортированы, но все штука, которая не то, что я хочу.
так, как мне это сделать? Как выбрать только те предметы, которые могут поместиться в сумку?
2 ответов
Я не работал с PostgreSQL. Тем не менее, мое лучшее предположение будет использовать встроенное представление.
SELECT a.*
FROM (
SELECT s.*, sum(volume) OVER previous_rows AS total
FROM stuff AS s
WINDOW previous_rows AS (
ORDER BY priority desc
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)
ORDER BY priority DESC
) AS a
WHERE a.total < 1000;
Я не знаю, квалифицируется ли это как "более элегантный", но он написан иначе, чем решение Cybernate (хотя это по существу то же самое)
WITH window_table AS ( SELECT s.*, sum(volume) OVER previous_rows as total FROM stuff s WINDOW previous_rows as (ORDER BY priority desc ROWS between UNBOUNDED PRECEDING and CURRENT ROW) ) SELECT * FROM window_table WHERE total < 1000 ORDER BY priority DESC
Если под "более элегантным" вы подразумеваете то, что избегает суб-выбора, то ответ "нет"