我一直在考虑这个问题几个小时而现在没有运气,所以我虽然SO上的人也许可以提供帮助:)。
我有一张表格,里面有关于商店处理量的数据。可以从该表中查询下面显示的前三列。我要做的是添加第4列,基本上是关于商店是否处理过> = $ 150的标志,如果是,则显示相应的日期。这种方式的工作方式是商店超过150美元的第一个例子是显示的日期。在第一个实例激活日期被命中后,后续处理量不计算。例如,对于商店4,只有一个激活日期的实例。
store_id sales_volume date activated_date
----------------------------------------------------
2 5 03/14/2012
2 125 05/21/2012
2 30 11/01/2012 11/01/2012
3 100 02/06/2012
3 140 12/22/2012 12/22/2012
4 300 10/15/2012 10/15/2012
4 450 11/25/2012
5 100 12/03/2012
有关如何构建第四列的任何见解?提前谢谢!
答案 0 :(得分:1)
解决方案首先计算累计销售额。然后,只有累积销售额首次通过$ 150级别时才需要激活日期。添加当前销售额时会发生这种情况,将累积金额推到阈值以上。以下case
表达式处理此问题。
select t.store_id, t.sales_volume, t.date,
(case when 150 > cumesales - t.sales_volume and 150 <= cumesales
then date
end) as ActivationDate
from (select t.*,
sum(sales_volume) over (partition by store_id order by date) as cumesales
from t
) t
如果你有一个不支持累积金额的旧版Postgres,你可以通过以下子查询获得累计销售额:
(select sum(sales_volume) from t t2 where t2.store_id = t.store_id and t2.date <= t.date) as cumesales
答案 1 :(得分:1)
您可以LEFT JOIN
到一个表格,计算超过每家商店150美元限额的第一个日期:
SELECT t.*, b.activated_date
FROM tbl t
LEFT JOIN (
SELECT store_id, min(thedate) AS activated_date
FROM (
SELECT store_id, thedate
,sum(sales_volume) OVER (PARTITION BY store_id
ORDER BY thedate) AS running_sum
FROM tbl
) a
WHERE running_sum >= 150
GROUP BY 1
) b ON t.store_id = b.store_id AND t.thedate = b.activated_date
ORDER BY t.store_id, t.thedate;
第一天的计算必须分两步完成,因为累积运行总和的窗函数必须在单独的SELECT
中应用。
另一个窗口函数而不是LEFT JOIN
。可能不会更快。使用EXPLAIN ANALYZE
进行测试。
SELECT *
,CASE WHEN running_sum >= 150 AND thedate = first_value(thedate)
OVER (PARTITION BY store_id, running_sum >= 150 ORDER BY thedate)
THEN thedate END AS activated_date
FROM (
SELECT *
,sum(sales_volume)
OVER (PARTITION BY store_id ORDER BY thedate) AS running_sum
FROM tbl
) b
ORDER BY store_id, thedate;
->sqlfiddle展示了两者。