PostgreSQL:选择行,直到单个列的减少量超过阈值

时间:2017-11-26 01:01:18

标签: sql postgresql distinct

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

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

我已经在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函数,虽然我不知道从哪里开始这种聚合查询。

如果有人有任何想法或技术诀窍,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

将唯一列(主键)添加到窗口函数的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
);

答案 1 :(得分:1)

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

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;