2014-04-11 35 views
0

我在查询支持票数据库,每张票都有一个“打开日期”和“日期关闭”的列。门票经常保持开放多天,所以我们需要能够拉出每天开门票的数量。
例如,对于4/8/14,我们需要知道4/8开了多少张门票,加上4/8之前开放的未关闭门票的总数,但在上午12:00仍然开放在4月8日(可能会或可能没有在4/8期间或之后关闭)。使用SQL查询,我如何选择范围内的每个日期?

对于单个日期来说,这看起来很简单,但现在我需要编写一个查询来提取完整​​的日期范围。
例如,我们需要编写一个查询,以返回每个日期在1/1/14和4/10/14之间的日期以及每个日期打开的总票数(包括打开0票的日期)。

这可能只使用查询或子查询,而不使用任何存储过程或临时数据表?
我们目前正在将数据提取到Excel中并计算其中的日期统计信息,但Excel不是一个可扩展的解决方案,我们希望让SQL执行此项工作,以便我们可以将此报告迁移到SSRS(SQL Server Reporting Services)在路上。

+1

IK的答案将让你关闭,但它不会给你日期没有门票打开。为此,您需要某种日期表,您可以外部连接到该表。 – Andrew

回答

4

您的问题对我来说并不是很清楚,但对于SQLServer 2005或更高版本(对于Date类型,SQLServer 2008或更高版本),您可以创建日历。这一个办法做到这一点

WITH [counter](N) AS 
(SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
SELECT 1) 
, days(N) AS (SELECT row_number() over (ORDER BY (SELECT NULL)) FROM [counter]) 
, months (N) AS (SELECT N - 1 FROM days WHERE N < 13) 
SELECT DISTINCT CAST(DATEADD(DAY, days.n, 
          DATEADD(MONTH, months.n, '20131231') 
          ) AS date) 
FROM months 
    CROSS JOIN days 
ORDER BY 1 

如果您需要更多年刚加入新CTE相应

SQLFiddle

+0

它花了一些修补,但我想出了如何添加CTE多年。 :)这很好,因为它没有达到100次递归的限制,即使我试着做几年的日期序列。 – Giffyguy

+1

没有必要递归的:添加CTE年(N)类似于月,新CTE添加到交叉连接(月交叉连接天CROSS JOIN年),并插入DATEADD一个新的水平,以增加当年 – Serpiton

+0

是,这很好。再次感谢! – Giffyguy

0

如果没有某种包含每行可能日期的行的日期表,就不能这样做。创建日期表非常简单,具体取决于您的RDBMS和您的要求。