TSQL每个星期一使用不同的行累积行

时间:2017-01-04 19:11:48

标签: sql-server sql-server-2008

我试图获得一个返回我每天参加过的客户的查询,并且我有这个数据集:

fecha      RecargadorPDV
2016/12/19     1
2016/12/19     2
2016/12/19     3
2016/12/20     1
2016/12/20     4
2016/12/20     5
2016/12/21     2
2016/12/21     6
2016/12/21     7
2016/12/21     8
..
...
2016/12/26     1
2016/12/26     2
2016/12/26     1
2016/12/27     2
2016/12/27     6
2016/12/27     7
2016/12/27     8

but the output I'd want to have is this:


             date          attended    acum_customers
            2016/12/19     3            3  -- Every monday it restart
            2016/12/20     3            5  
            2016/12/21     4            8  
            .
            ..
            2016/12/26     3        3 -- Every monday it restart
            2016/12/27     4        3 
            .
            ..

正如您所看到的,每个星期一都会重新启动值,如果某些客户处于某个日期并且第二天存在,则需要将其忽略。

2 个答案:

答案 0 :(得分:1)

这是一个版本,可以返回任意日期所需的内容。我已将样本数据包含一整周+两天以确认其功能。

DECLARE @t table (fecha date,
    RecargadorPDV int
    )
INSERT INTO @t VALUES
('2016/12/19', 1),
('2016/12/19', 2),
('2016/12/19', 3),
('2016/12/20', 1),
('2016/12/20', 4),
('2016/12/20', 5),
('2016/12/21', 2),
('2016/12/21', 6),
('2016/12/21', 7),
('2016/12/21', 8),
('20161222', 12),
('20161222', 1),
('20161222', 8),
('20161223', 11),
('20161223', 13),
('20161223', 15),
('20161223', 9),
('20161224', 1),
('20161225', 22),
('2016/12/26', 1),
('2016/12/26', 2),
('2016/12/26', 1),
('2016/12/27', 2),
('2016/12/27', 6),
('2016/12/27', 7),
('2016/12/27', 8)
;

With a as (
    SELECT DISTINCT 
        fecha,
        Dateadd(day, -(
            case 
                when datepart(weekday, fecha) >=2
                    THEN datepart(weekday, fecha) - 2
                ELSE 6
        END), fecha) as LastMonday
    FROM @t
    )
SELECT 
    a.fecha as [date],
--  count(Distinct(CASE when t.fecha = a.fecha Then t.recargadorPDV else -1 END)) - 1 as attended,
    SUM(CASE when t.fecha = a.fecha Then 1 else 0 END) as attended,
    Count(distinct recargadorPDV) as acum_customers
FROM @t t
INNER JOIN a
    ON t.fecha BETWEEN a.LastMonday and a.fecha

Group by a.fecha
ORDER BY a.fecha

以上(已更正)的输出为:

date        attended  acum_customers
2016-12-19  3         3
2016-12-20  3         5
2016-12-21  4         8
2016-12-22  3         9
2016-12-23  4         13
2016-12-24  1         13
2016-12-25  1         14
2016-12-26  3         2
2016-12-27  4         5

答案 1 :(得分:0)

我认为您的第二周acum_customers已根据测试数据关闭,因此请检查。我还假设recargadorPDV每天只能参加一次,因为它是唯一的,所以我删除了下面提到的一条记录。有了......这应该可以得到你想要的东西。如果需要更多解释,请告诉我。

--change the @@DATEFIRST from 7 (english default) to 1 for the start of the week calculations
SET DATEFIRST  1;

--load some test data
declare @table table (fetcha datetime, recargadorPDV int)
insert into @table(fetcha, recargadorPDV) 
values
('2016/12/19',1),
('2016/12/19',2),
('2016/12/19',3),
('2016/12/20',1),
('2016/12/20',4),
('2016/12/20',5),
('2016/12/21',2),
('2016/12/21',6),
('2016/12/21',7),
('2016/12/21',8),
                    --this is the break in the weeks
('2016/12/26',1),
('2016/12/26',2),
--('2016/12/26',1), -- removed this value since a unique ID shouldn't be allowed to attend twice for a single day
('2016/12/27',2),
('2016/12/27',6),
('2016/12/27',7),
('2016/12/27',8)


--temp table to hold some aggregated data
if object_id('tempdb..#tempT') is not null drop table #tempT

select 
    y.YR
    ,y.WK
    ,y.fetcha
    ,count(y.recargadorPDV) as attend
    ,sum(y.CTforWK) as accum
into #tempT
from(
    select x.* 
    from
        (select
            fetcha
            ,recargadorPDV
            ,datepart(yy,fetcha) as YR
            ,datepart(wk,fetcha) as WK
            --the case statment is my way of assigning 1 to each recargadorPDV ONLY once for each week so the running total is correct, ignoring duplicates as you stated
            ,case when count(recargadorPDV) over (partition by datepart(yy,fetcha), datepart(wk,fetcha), recargadorPDV order by fetcha) = 1 then 1 else 0 end as CTforWK
        from @table) x) y
group by
    y.YR
    ,y.WK
    ,y.fetcha


--see the inital results without the running total
select * from #tempT

--see the final results with the running total
select
    a.fetcha
    ,a.attend
    ,sum(x.accum) as acum_customers
from #tempT a
inner join #tempT x on x.fetcha <= a.fetcha and x.YR = a.YR and x.WK = a.WK
group by a.fetcha, a.attend
order by a.fetcha

--change back the @@DATEFIRST setting
SET DATEFIRST  7;