GROUP BY DAY,CUMULATIVE SUM

时间:2015-06-02 09:57:53

标签: sql-server linq

我在MSSQL中有一个表,结构如下:

PersonId
StartDate
EndDate

我需要能够在日期范围内或在给定日期显示表格中不同人数。

作为一个例子,我需要每天显示每天的总数,例如如果我们在6月1日有2个条目,6月2日有3个条目,6月3日有1个条目,系统应显示以下结果:

1st June: 2
2nd June: 5
3rd June: 6

但是,例如在6月2日的参赛作品中,结束日期为6月2日,而6月3日的结果仅为5。

是否有人能够协助解决这个问题。

由于

更新

这是我到目前为止似乎有效的方法。有没有更好的解决方案,因为我的解决方案只能让我使用数字。我还需要在另一个专栏上失业 - 失业意味着要么没有参加表格,要么没有参加任何其他参赛作品。

CREATE TABLE #Temp(CountTotal int NOT NULL, CountDate datetime NOT NULL); 

DECLARE @StartDT DATETIME

SET @StartDT =  '2015-01-01 00:00:00'

WHILE @StartDT < '2015-08-31 00:00:00'

BEGIN
   INSERT INTO #Temp(CountTotal, CountDate)
   SELECT COUNT(DISTINCT PERSON.Id) AS CountTotal, @StartDT AS CountDate     FROM PERSON 

   INNER JOIN DATA_INPUT_CHANGE_LOG ON PERSON.DataInputTypeId = DATA_INPUT_CHANGE_LOG.DataInputTypeId AND PERSON.Id = DATA_INPUT_CHANGE_LOG.DataItemId 
   LEFT OUTER JOIN PERSON_EMPLOYMENT ON PERSON.Id = PERSON_EMPLOYMENT.PersonId 

   WHERE PERSON.Id > 0  AND DATA_INPUT_CHANGE_LOG.Hidden = '0' AND DATA_INPUT_CHANGE_LOG.Approved = '1' 

   AND ((PERSON_EMPLOYMENT.StartDate <= DATEADD(MONTH,1,@StartDT) AND PERSON_EMPLOYMENT.EndDate IS NULL) 


   OR (@StartDT BETWEEN PERSON_EMPLOYMENT.StartDate AND PERSON_EMPLOYMENT.EndDate) AND PERSON_EMPLOYMENT.EndDate IS NOT NULL)

   SET @StartDT = DATEADD(MONTH,1,@StartDT)
END

select * from #Temp
drop TABLE #Temp

2 个答案:

答案 0 :(得分:0)

您可以通过创建数据来执行此操作,其中每个开始日期为+1事件,结束日期为-1,然后计算运行总计。

例如,如果您的数据是这样的

PersonId   StartDate   EndDate
1          20150101    20150201
2          20150102    20150115
3          20150101    

首先创建一个如下所示的数据集:

EventDate   ChangeValue
20150101    +2
20150102    +1
20150115    -1
20150201    -1

如果你使用总计,你会得到这个:

EventDate   Total
2015-01-01  2
2015-01-02  3
2015-01-15  2
2015-02-01  1

你可以用这样的东西得到它:

select
  p.eventdate,
  sum(p.changevalue) over (order by p.eventdate asc) as total
from
(
  select startdate as eventdate, sum(1) as changevalue from personnel group by startdate
  union all
  select enddate, sum(-1) from personnel where enddate is not null group by enddate
) p
order by p.eventdate asc

具有sum()的窗口函数需要SQL Server 2012.如果您使用的是旧版本,则可以检查其他选项以运行总计。

我在SQL Fiddle

中的例子

如果您的日期没有任何事件,并且您也需要显示这些事件,那么最佳选择可能是为您需要的整个范围创建一个单独的日期表,例如1.1.2000 - - 31.12.2099。

- 编辑 -

要获得特定日期的计数,可以使用相同的逻辑,但只需将所有内容汇总到那一天:

declare @eventdate date

set @eventdate = '20150117'

select
  sum(p.changevalue)
from
(
  select startdate as eventdate, 1 as changevalue from personnel 
  where startdate <= @eventdate
  union all
  select enddate, -1 from personnel 
  where enddate < @eventdate
) p

希望这没关系,因为SQL Fiddle似乎无法使用,所以无法测试。

答案 1 :(得分:0)

您可以使用以下查询。 cte部分是在开始日期和结束日期之间生成一组序列日期。

DECLARE @ViewStartDate DATETIME
DECLARE @ViewEndDate DATETIME

SET @ViewStartDate = '2015-01-01 00:00:00.000';
SET @ViewEndDate = '2015-02-25 00:00:00.000';

;WITH Dates([Date])
AS
(
    SELECT @ViewStartDate
    UNION ALL
    SELECT DATEADD(DAY, 1,Date)  
    FROM Dates
    WHERE DATEADD(DAY, 1,Date) <= @ViewEndDate
)
SELECT [Date], COUNT(*) 
FROM Dates
    LEFT JOIN PersonData ON Dates.Date >= PersonData.StartDate 
    AND Dates.Date <= PersonData.EndDate
GROUP By [Date]
  • 将PersonData替换为您的表名

  • 如果startdate和enddate列可以为null,则需要添加 加入的附加条件

  • 假设一个人在同一日期范围内只有一条记录