Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL分组和运行日期范围的未清项目总数_Sql_Sql Server_Tsql_Stored Procedures - Fatal编程技术网

SQL分组和运行日期范围的未清项目总数

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

为了简单起见,我有一个项目表,其中包含项目列表的项目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      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