Sql 基于聚合值显示附加列的查询

Sql 基于聚合值显示附加列的查询,sql,postgresql,Sql,Postgresql,我已经考虑这个问题好几个小时了,但运气不好,所以我想so上的人可能会帮上忙:) 我有一个关于商店处理量的数据表。下面显示的前三列可以从该表中查询。我想做的是添加一个第四列,它基本上是一个关于商店是否处理了>=$150的标志,如果是,将显示相应的日期。这种方式的工作原理是,商店第一次超过150美元是显示日期。在达到激活日期的第一个实例后,后续处理卷不计算在内。例如,对于Store4,只有一个激活日期的实例 store_id sales_volume date activated

我已经考虑这个问题好几个小时了,但运气不好,所以我想so上的人可能会帮上忙:)

我有一个关于商店处理量的数据表。下面显示的前三列可以从该表中查询。我想做的是添加一个第四列,它基本上是一个关于商店是否处理了>=$150的标志,如果是,将显示相应的日期。这种方式的工作原理是,商店第一次超过150美元是显示日期。在达到激活日期的第一个实例后,后续处理卷不计算在内。例如,对于Store4,只有一个激活日期的实例

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

关于如何构建第四个专栏有什么见解吗?提前谢谢

解决方案从计算累计销售额开始。然后,只有当累计销售额首次超过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
选择t.store\u id、t.sales\u volume、t.date、,
(当150>cumesales时的情况-t.销售量和150变量1
您可以
左键联接到一个表,该表计算出第一个超过每家店铺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
中应用

变式2 另一个窗口函数,而不是
左连接
。可能不会更快。请使用
解释分析
进行测试

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;

演示两者。

您对哪些版本的PostgreSQL感兴趣?不幸的是,8.3。下面人们建议的窗口函数从8.4开始工作。这就是为什么我问的原因,窗口函数(PostgreSQL在8.4中获得了支持)自然适合这种情况。您是否有可能升级到8.4?8.3(或已在)它的生命结束了。谢谢你,这太棒了!我使用了子查询方法,但学会了累积总和以备将来使用!另外,我刚买了你的书,很高兴能试一试!谢谢你!我为此绞尽脑汁,最终用Excel做了这件事,但这太棒了!肯定会帮我节省时间。
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;