找出哪些客户在 10 天内购买了超过 75 美元的商品
Posted
技术标签:
【中文标题】找出哪些客户在 10 天内购买了超过 75 美元的商品【英文标题】:Find out which customers made purchases over $75 within a 10 day period 【发布时间】:2014-11-14 13:51:32 【问题描述】:我有下表:
purchase
---------------------
customer VARCHAR
cost DECIMAL
purchase_date DATE
我想获取在 10 天内总购买金额为 75 美元或以上的所有客户的列表。
以下 SQL 给出了过去 10 天内的金额:
SELECT customer
FROM purchase
WHERE purchase_date >= (CURRENT_DATE - 10)
GROUP BY customer
HAVING sum(cost) >= 75;
如何扩展此查询以包括任何 10 天?
Postgresql 已经有一个名为 generate_series 的函数,它可以为我提供从第一个到最后一个的所有购买日期:
SELECT generate_series((select min(purchase_date) from purchase),
(select max(purchase_date) from purchase),
'1 day') as generated_date;
现在我需要修改上述查询以使用生成的系列中的天数。这就是我卡住的地方。如何为第二个查询中的每个日期运行第一个查询,用purchase_date >= (generated_date - 10)
替换purchase_date >= (CURRENT_DATE - 10)
?
【问题讨论】:
【参考方案1】:我认为您可以使用如下所示的横向连接。不过我还没能测试它。
SELECT *
FROM your_table y1
LEFT JOIN LATERAL(
SELECT Customer, SUM(Cost) Cost
FROM your_table y2
WHERE y1.Customer = y2.Customer
AND y2.purchase_date
BETWEEN y1.purchase_date - INTERVAL '10 Day' AND y1.purchase_date
GROUP BY Customer
) AS lat ON TRUE
WHERE lat.cost >= 75
ORDER BY Customer;
这应该返回前 10 天的费用总和 >= 75 的行。
【讨论】:
另外,查询似乎有点慢。 不确定是否可以通过交叉连接来做到这一点;一个相关的子查询应该可以工作,但这几乎就是我认为的横向连接。性能可能会很差,因为您要为每一行的前 10 行执行求和,这是一个非常昂贵的操作。使用 Postgresql 可能有更好的方法来做到这一点,但我对 PG 不太熟悉,无法想出更好的方法。 我可能需要缓存这个,这给了我正确的结果,但页面加载需要 8 秒以上... 加入 generate_series 而不是自我加入,这会更快! @Ramin 啊酷。就像我说的,我无法测试它,所以我想还有很大的改进空间。【参考方案2】:受 jpw 的启发,使用 generate_series 加入购买给了我相同的结果,但速度更快:
SELECT distinct customer
from generate_series((select min(date) from purchase),
(select max(date) from purchase),
'1 day') as generated_date,
LATERAL(
SELECT customer
FROM purchase
where date
BETWEEN (generated_date - INTERVAL '10 day') AND generated_date
GROUP BY customer
having SUM(cost) >= 75
) p
ORDER BY customer;
【讨论】:
以上是关于找出哪些客户在 10 天内购买了超过 75 美元的商品的主要内容,如果未能解决你的问题,请参考以下文章