Postgresql 中通过窗口函数过滤结果

问题描述 投票:0回答:2

好吧,最初这只是我们和朋友开的一个玩笑,但后来变成了有趣的技术问题:)

我有以下

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

如果我删除此过滤器,总列会得到正确计算,结果会正确排序,但all内容会被选中,这不是我想要的。

那么,我该怎么做呢?如何只选择可以放入包中的物品?

sql postgresql window-functions
2个回答
24
投票

我不知道这是否符合“更优雅”的条件,但它的编写方式与 Cybernate 的解决方案不同(尽管本质上是相同的)

与window_table AS
(
   选择 s.*,
          sum(volume) OVER previous_rows 作为总计
   FROM 东西
   WINDOW previous_rows 为
        (按 UNBOUNDED PRECEDING 和 CURRENT ROW 之间的优先级 desc ROWS 排序)
)
选择 *
从窗口表
总共在哪里 < 1000
ORDER BY priority DESC 

如果“更优雅”是指避免子选择的东西,那么答案是“否”


21
投票

我没有使用过 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;
© www.soinside.com 2019 - 2024. All rights reserved.