简体   繁体   English

SQL在特定日期的运行总和

[英]SQL running sum on particular dates

Let's assume this table: 让我们假设这个表:

Dpt ctd dte
A   1   2014-01-06
A   2   2014-01-07
A   1   2014-01-07
B   1   2014-01-06
B   1   2014-01-07
A   2   2014-01-09
B   1   2014-01-10
A   1   2014-01-11
B   1   2014-01-13
A   2   2014-01-13

I would like to calcualte the running sum on every sunday: 我想计算每个星期天的累计金额:

A   1   2014-01-06
B   1   2014-01-06
A   9   2014-01-13
B   4   2014-01-13

How can I do this using an SQL query? 如何使用SQL查询做到这一点? Running PostgreSQL 9.3 运行PostgreSQL 9.3

You get a running total with SUM OVER. 您的SUM OVER可获得总计。 As you can have multiple records per day for a dpt, you must group by dpt and day first and run the total over the SUM(ctd). 由于您每天可能有多个dpt记录,因此您必须先按dpt分组,然后按天分组,然后对SUM(ctd)进行总计。 Afterwards remove days that are not Sunday. 然后删除不是星期日的日子。

select *
from
(
  select dpt, dte, sum(sum(ctd)) over (partition by dpt order by dte) as total
  from mytable
  group by dpt, dte
) distinct_days
where to_char(dte,'D') = '1' -- Sunday is '1', Monday is '2', etc.
order by dte, dpt;

(You can achieve the same by using SUM OVER on all records first and remove duplicates in your results with DISTINCT. To me, however, grouping first feels more natural.) (您可以先在所有记录上使用SUM OVER,然后使用DISTINCT删除结果中的重复项,以实现相同的目的。但是,对我来说,首先进行分组更自然。)

Here's how we could do it in Oracle. 这是我们在Oracle中可以做到的方式。 I'm quite sure that the same can be done using PostgreSQL also. 我很确定也可以使用PostgreSQL进行相同的操作。 2014-01-06 and 2014-01-13 are Mondays, I suppose. 我想2014-01-06和2014-01-13是星期一。

with data_ as (select dpt, ctd, to_date(dte,'yyyy-mm-dd') dte from
(select 'A' dpt, 1 ctd, '2014-01-06' dte from dual
union all
select 'A' ,2 , '2014-01-07' from dual
union all
select 'A' ,1 , '2014-01-07' from dual
union all
select 'B' ,1 , '2014-01-06' from dual
union all
select 'B' ,1 , '2014-01-07' from dual
union all
select 'A' ,2 , '2014-01-09' from dual
union all
select 'B' ,1 , '2014-01-10' from dual
union all
select 'A' ,1 , '2014-01-11' from dual
union all
select 'B' ,1 , '2014-01-13' from dual
union all
select 'A' ,2 , '2014-01-13' from dual))


select dpt, dte, ord runn_sum
from (select dpt, dte, trim(both from to_char(dte,'Day')) day_,
sum(ctd) over (partition by dpt order by dte) ord
from data_) where day_ = 'Monday'
order by 2 asc;
with t (dpt, ctd, dte) as (
    values
        ('a', 1, '2014-01-06'::date),
        ('a', 2, '2014-01-07'),
        ('a', 1, '2014-01-07'),
        ('b', 1, '2014-01-06'),
        ('b', 1, '2014-01-07'),
        ('a', 2, '2014-01-09'),
        ('b', 1, '2014-01-10'),
        ('a', 1, '2014-01-11'),
        ('b', 1, '2014-01-13'),
        ('a', 2, '2014-01-13')
)
select dte, dpt, total
from (
    select
        dte, dpt,
        sum(ctd) over(partition by dpt order by dte) as total
    from t
) s
where extract(isodow from dte) = 1
order by dte, dpt
;
    dte     | dpt | total 
------------+-----+-------
 2014-01-06 | a   |     1
 2014-01-06 | b   |     1
 2014-01-13 | a   |     9
 2014-01-13 | b   |     4

This does not requires to have entries on sundays (and it really works with sundays, not with mondays): 这不需要在星期日有条目(它确实适用于星期日,而不适用于星期一):

with t (dpt, ctd, dte) as (
  values ('a', 2, date '2014-01-05'),
     ('a', 1, '2014-01-06'),
     ('a', 2, '2014-01-07'),
     ('a', 1, '2014-01-07'),
     ('b', 1, '2014-01-06'),
     ('b', 1, '2014-01-07'),
     ('a', 2, '2014-01-09'),
     ('b', 1, '2014-01-10'),
     ('a', 1, '2014-01-11'),
     ('b', 1, '2014-01-13'),
     ('a', 2, '2014-01-13')
)
select dpt, monday + 6 sunday,
       sum(ctd_sum) over(partition by dpt order by monday) total
from (
  select dpt, date(date_trunc('week', dte)) monday, sum(ctd) ctd_sum
  from   t
  group by 1, 2
) sub;

 dpt |    dte     | total 
-----+------------+-------
 a   | 2014-01-05 |     2 
 a   | 2014-01-12 |     9 
 a   | 2014-01-19 |    11 
 b   | 2014-01-12 |     3 
 b   | 2014-01-19 |     4 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM