[英]Convert Date Range to Individual Days
名为VolumeRequest
的表按帐户存储日期范围内的卷请求。
AccountId StartDate EndDate DailyVolume
670 2013-07-01 00:00:00.000 2013-07-31 00:00:00.000 10
670 2013-07-01 00:00:00.000 2013-07-31 00:00:00.000 1050
670 2013-07-10 00:00:00.000 2013-07-10 00:00:00.000 -350
670 2013-07-24 00:00:00.000 2013-07-26 00:00:00.000 -350
673 2013-06-01 00:00:00.000 2013-07-31 00:00:00.000 233
我需要每天显示请求,其中对于给定的日期范围(例如7月份的月份),按帐户按天对总和进行汇总,如下所示。 需要针对给定的报告日期修剪批量请求的日期开始日期和结束日期
AccountId Date Volume
670 2013-07-01 00:00:00.000 1060
670 2013-07-02 00:00:00.000 1060
.
.
670 2013-07-10 00:00:00.000 710
.
.
670 2013-07-24 00:00:00.000 710
670 2013-07-25 00:00:00.000 710
670 2013-07-26 00:00:00.000 710
.
.
670 2013-07-31 00:00:00.000 1060
673 2013-07-01 00:00:00.000 233
.
.
673 2013-07-31 00:00:00.000 233
现在,我正在使用表变量和循环来实现它,我知道这不是编码的好方法。
DECLARE @sDate DATETIME, @eDate DATETIME , @volume DECIMAL (10, 4), rstartdate DATETIME, @renddate DATETIME , @loopcount INT
SET @sdate = '4/1/2013'
SET @edate = '4/30/2013'
DECLARE @VolumeRequest TABLE
(
ID INT IDENTITY (1, 1) PRIMARY KEY,
Aid INT,
Startdate DATETIME,
Enddate DATETIME,
volume DECIMAL (14, 4)
)
DECLARE @DailyRequest TABLE
(
ID INT IDENTITY (1, 1) PRIMARY KEY,
Accountid INT,
ReadDate DATETIME,
Volume DECIMAL (14, 4)
)
INSERT INTO @VolumeRequest
SELECT Accountid,
( CASE
WHEN @sdate > startdate THEN @sdate
ELSE startdate
END ),
( CASE
WHEN @edate < enddate THEN @edate
ELSE enddate
END ),
dailyvolume
FROM VolumeRequest
WHERE Startdate <= @edate
AND Enddate >= @sdate
AND isnull (deprecated, 0) != 1
--loop to breakdown the volume requests into daily requests
SET @loopcount = 1
WHILE @loopcount <= (SELECT MAX(ID)
FROM @VolumeRequest)
BEGIN
SELECT @volume = volume,
@rstartdate = Startdate,
@renddate = Enddate
FROM @VolumeRequest
WHERE ID = @loopcount
WHILE @rstartdate <= @renddate
BEGIN
INSERT INTO @DailyRequest
SELECT @currentaid,
@rstartdate,
@volume
SET @rstartdate = DATEADD(day, 1, @rstartdate)
END
SET @LoopCount = @LoopCount + 1
END
我正在寻找不涉及循环或游标的方法。 我发现了一个类似的问题 。 那里的答案并没有帮助我。
我喜欢使用日期表,例如
CREATE TABLE #Dates(
DateId INT,
CalendarDate DATETIME)
填满您所需范围内的日期。 我使用该表联接诸如VolumeRequest之类的表,以检索您请求的输出。
SELECT
v.AccountId,
d.CalendarDate,
SUM(v.DailyVolume)
FROM
#Dates d INNER JOIN
VolumeRequest v ON
d.CalendarDate >= v.StartDate AND
d.CalendarDate <= v.EndDate
group by
d.CalendarDate,
v.AccountId
填写#Dates表,我使用类似以下的方法:
declare @startdate datetime = '6/1/13', @enddate datetime = '7/31/13'
create table #Dates(CalendarDate datetime)
insert into #Dates(CalendarDate)
select
dateadd(dd, rid-1, @startdate) as calendardate
from (
select
ROW_NUMBER() over(order by o.object_id) as rid
From
sys.objects o cross apply
sys.objects o2
) dates
where
dateadd(dd, rid-1, @startdate) >= @startdate and dateadd(dd, rid-1, @startdate) <= @enddate
修改以满足您的日期范围需求。
使用WITH子句和递归,我们可以生成Days
表,其中包含MIN和MAX日期之间的所有日期。 然后生成具有不同AccountID
表Accounts
。 最后,将所有这些表联接起来,并用SUM分组。
WITH MINMAX as
( SELECT MIN(StartDate) as MinDate,
MAX(EndDate) as MaxDate
from T
),
DAYS as
( SELECT MinDate as D from MINMAX
UNION ALL
SELECT D+1 as D FROM DAYS WHERE D+1<=
(
SELECT MaxDate FROM MINMAX
)
),
Accounts as
(
select distinct AccountID from T
)
select A.AccountId,Days.D,sum(T.DailyVolume) from Days
CROSS JOIN Accounts A
JOIN T on A.AccountID=T.AccountID
AND
Days.D between T.StartDate and T.EndDate
GROUP BY A.AccountId,Days.D
ORDER BY A.AccountId,Days.D
OPTION (MAXRECURSION 10000)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.