SQL分组和运行日期范围的未清项目总数
为了简单起见,我有一个项目表,其中包含项目列表的项目ID、开始日期和结束日期SQL分组和运行日期范围的未清项目总数,sql,sql-server,tsql,stored-procedures,Sql,Sql Server,Tsql,Stored Procedures,为了简单起见,我有一个项目表,其中包含项目列表的项目ID、开始日期和结束日期 ItemID StartDate EndDate 1 1/1/2011 1/15/2011 2 1/2/2011 1/14/2011 3 1/5/2011 1/17/2011 ... 我的目标是能够将此表连接到具有连续日期列表的表, 并说明在特定日期打开了多少项,以及累计打开了多少项 Date ItemsOp
ItemID StartDate EndDate
1 1/1/2011 1/15/2011
2 1/2/2011 1/14/2011
3 1/5/2011 1/17/2011
...
我的目标是能够将此表连接到具有连续日期列表的表,
并说明在特定日期打开了多少项,以及累计打开了多少项
Date ItemsOpened CumulativeItemsOpen
1/1/2011 1 1
1/2/2011 1 2
...
我可以看到如何使用WHILE循环来实现这一点,
但这对性能有影响。我想知道怎么做
这可以通过基于集合的方法来实现吗 这可能会给你想要的
SELECT DATE,
SUM(ItemOpened) AS ItemsOpened,
COUNT(StartDate) AS ItemsOpenedCumulative
FROM
(
SELECT d.Date, i.startdate, i.enddate,
CASE WHEN i.StartDate = d.Date THEN 1 ELSE 0 END AS ItemOpened
FROM Dates d
LEFT OUTER JOIN Items i ON d.Date BETWEEN i.StartDate AND i.EndDate
) AS x
GROUP BY DATE
ORDER BY DATE
这假定您的日期值是日期数据类型。或者,日期是没有时间值的日期时间。您可能会发现这很有用。可以用一张桌子来代替重复部分。为了演示它的工作原理,我必须填充某种日期表。正如您所看到的,实际的sql简短而简单
DECLARE @i table (itemid INT, startdate DATE, enddate DATE)
INSERT @i VALUES (1,'1/1/2011', '1/15/2011')
INSERT @i VALUES (2,'1/2/2011', '1/14/2011')
INSERT @i VALUES (3,'1/5/2011', '1/17/2011')
DECLARE @from DATE
DECLARE @to DATE
SET @from = '1/1/2011'
SET @to = '1/18/2011'
-- the recusive sql is strictly to make a datelist between @from and @to
;WITH cte(Date)
AS (
SELECT @from DATE
UNION ALL
SELECT DATEADD(day, 1, DATE)
FROM cte ch
WHERE DATE < @to
)
SELECT cte.Date, sum(case when cte.Date=i.startdate then 1 else 0 end) ItemsOpened, count(i.itemid) ItemsOpenedCumulative
FROM cte
left join @i i on cte.Date between i.startdate and i.enddate
GROUP BY cte.Date
OPTION( MAXRECURSION 0)
如果您使用的是SQL Server 2005+,则可以在函数的其他帮助下使用获取运行总数,如下所示:
WITH grouped AS (
SELECT
d.Date,
ItemsOpened = COUNT(i.ItemID),
rn = ROW_NUMBER() OVER (ORDER BY d.Date)
FROM Dates d
LEFT JOIN Items i ON d.Date BETWEEN i.StartDate AND i.EndDate
GROUP BY d.Date
WHERE d.Date BETWEEN @FilterStartDate AND @FilterEndDate
),
cumulative AS (
SELECT
Date,
ItemsOpened,
ItemsOpenedCumulative = ItemsOpened
FROM grouped
WHERE rn = 1
UNION ALL
SELECT
g.Date,
g.ItemsOpened,
ItemsOpenedCumulative = g.ItemsOpenedCumulative + c.ItemsOpened
FROM grouped g
INNER JOIN cumulative c ON g.Date = DATEADD(day, 1, c.Date)
)
SELECT *
FROM cumulative
你能重新定义你所说的itemsopended和ItemsOpenedCumulative是什么意思吗?您接受了一个答案,该答案表明ItemsOpened=此日期打开的项目数,ItemsOPenedCumulative=当前打开的项目数。我想删除我的答案,如果它是不正确的好点;我的专栏命名留下了混乱的空间。我一直在寻找当前打开的项目数。您是指累积列还是项目打开列?谢谢最后一件事,ItemsPotened是指ItemsPotenedon这一天吗?谢谢是的,itemsopended的意思是itemsopenedonthis。我相信上面的语法错误。使用累积AS时,应简单地将其累积为
WITH grouped AS (
SELECT
d.Date,
ItemsOpened = COUNT(i.ItemID),
rn = ROW_NUMBER() OVER (ORDER BY d.Date)
FROM Dates d
LEFT JOIN Items i ON d.Date BETWEEN i.StartDate AND i.EndDate
GROUP BY d.Date
WHERE d.Date BETWEEN @FilterStartDate AND @FilterEndDate
),
cumulative AS (
SELECT
Date,
ItemsOpened,
ItemsOpenedCumulative = ItemsOpened
FROM grouped
WHERE rn = 1
UNION ALL
SELECT
g.Date,
g.ItemsOpened,
ItemsOpenedCumulative = g.ItemsOpenedCumulative + c.ItemsOpened
FROM grouped g
INNER JOIN cumulative c ON g.Date = DATEADD(day, 1, c.Date)
)
SELECT *
FROM cumulative