【问题标题】:How do I limit a select by a sum?如何通过总和限制选择?
【发布时间】:2013-04-22 06:27:33
【问题描述】:

我想选择我库存中所有最便宜的玩具,总计 10.0 美元:

也就是说,我想做一些看起来像这样的事情:

select * from toy where sum(price) < 10.0 order by price;

什么是正确的 SQL?

为了更清楚,我将添加一个示例。 假设我的表中有这些项目:

       name       | price
------------------+-------
car               |     1
boat              |     2
telephone         |     8
gold bar          |    50

我的结果是:1 辆汽车和 1 艘船。

总计 3 美元的价格。我无法选择电话,因为它的金额为 13 美元,而且大于 10 美元。

有什么想法吗?

【问题讨论】:

  • 你在运行什么 RDBMS?
  • 记录是如何排序的?你有自动递增键吗?
  • 它们是随机排序的。我想按价格排序。

标签: sql postgresql sum limit


【解决方案1】:

试试:

SELECT a.name, max(a.price) price 
FROM Toy a
JOIN Toy b
  on a.price > b.price or (a.price=b.price and a.name>=b.name)
GROUP BY a.name
HAVING SUM(b.price) <= 10.0
order by 2

SQLFiddle here.

【讨论】:

  • +1 查询按照 OP 的要求工作。你能解释一下给定的查询吗?
  • @hims056:当然 - 对于Toy(别名 a)上的每条记录,查询链接到同一张表(别名 b)上价格较低(或价格相同但价格相同)的所有记录小于或等于名称),然后检查链接记录的价格加起来是否不超过 10。
  • 我会假设使用窗口函数来计算运行总和(请参阅 Clodoaldo 的答案)会更有效。
【解决方案2】:

SQL Fiddle

select name, price, total
from (
    select
        name, price,
        sum(price) over(
            order by price
            rows between unbounded preceding and current row
        ) total
    from toy
) s
where total <= 10
order by price

请注意,虽然between unbounded preceding and current row 是默认框架,但默认模式是range。所以必须至少声明rows unbounded preceding,因为当前行是帧结束默认值。

【讨论】:

  • 附带说明:指定rows between unbounded preceding and current row 并不是真正必要的,因为这是默认设置。
【解决方案3】:

这是使用递归 CTE 的实现。对此还有其他解决方案,您可以谷歌搜索“运行总计”。

WITH RECURSIVE CTE_RN  AS 
(
    SELECT *, ROW_NUMBER() OVER (ORDER BY Price) RN FROM Toys
)
, CTE_Rec AS
(
    SELECT name, price, rn FROM CTE_RN WHERE RN = 1
    UNION ALL
    SELECt r.name, a.price + r.price as price, r.rn FROM CTE_RN r
    INNER JOIN CTE_Rec a on a.RN + 1 = r.RN
    where a.price+r.price <= 10
 )
SELECT name, price as total_price FROM CTE_Rec

SQLFiddle Demo

PS:这很大程度上取决于 RDBMS,因此在开始时包含该信息很重要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多