PostgreSQL:选择行,直到单列的总和减少达到阈值

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

我想编写一个查询,从有序表中获取行,同时聚合一列的值,直到所述聚合值满足所需的阈值。

另一个标准是,通过阈值的违规行应包含在查询结果中。

我寻找了 PostgreSQL 中完成的其他解决方案,导致我创建了以下查询:

SELECT * FROM (
    SELECT *, SUM(amount) OVER (ORDER BY amount DESC) AS running_amount
    FROM public.orders WHERE price = 0.09) AS t
WHERE t.running_amount <= 15;

但是,此查询的问题是它代表 PostgreSQL 窗口查询,如果给定行的列值不唯一,则它会跳过所有行上列值的聚合。

不幸的是,窗口查询不支持考虑不同值列。

我听说的一些替代方案仍然可以通过创建 PostgreSQL 函数来实现这一点,尽管我不知道从哪里开始进行这种聚合查询。

如果有人有任何想法或专业知识,我将不胜感激。

sql postgresql aggregate-functions distinct
2个回答
4
投票

在窗口函数的

ORDER BY
子句中添加唯一列(主键),例如:

SELECT * FROM (
    SELECT *, SUM(amount) OVER (ORDER BY amount DESC, id) AS running_amount
    FROM public.orders WHERE price = 0.09
) AS t
WHERE t.running_amount <= 15;

如果缺乏独特的栏目,您可以使用系统栏目

ctid.


您可以使用

UNION ALL
来获取通过阈值的违规行,例如:

WITH cte AS (
    SELECT *, SUM(amount) OVER (ORDER BY amount DESC, id) AS running_amount
    FROM public.orders 
    WHERE price = 0.09
)
SELECT * 
FROM cte
WHERE running_amount <= 15
UNION ALL (
    SELECT * 
    FROM cte
    WHERE running_amount > 15
    LIMIT 1
);

4
投票

如果您想要最后一行(越过阈值的一行),您有两个相对简单的选择。我的偏好是:

SELECT o.*
FROM (SELECT o.*,
             SUM(amount) OVER (ORDER BY amount DESC) AS running_amount
      FROM public.orders
      WHERE price = 0.09
     ) o
WHERE o.running_amount - o.amount <= 15;

替代方案是窗口条款:

SELECT o.*
FROM (SELECT o.*,
             SUM(amount) OVER (ORDER BY amount DESC
                               ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
                              ) AS running_amount
      FROM public.orders
      WHERE price = 0.09
     ) o
WHERE o.running_amount <= 15;
© www.soinside.com 2019 - 2024. All rights reserved.