在两个列值之间选择日期

3
如果我有一个带有StartDate和EndDate列的表,我能否生成一个查询,返回包括范围内每一天的集合。我可以使用一个表变量并进行一些过程性代码,但我想知道是否有一种方法在查询中完成它。 例如,StartDate=2010年1月1日,EndDate=2010年1月5日,结果将是: - 2010年1月1日 - 2010年1月2日 - 2010年1月3日 - 2010年1月4日 - 2010年1月5日 对于具有StartDate和EndDate列的表中的每一行都适用。 *我使用的是SQL 2005。
2个回答

2

SQL Server 2005+:

WITH dates AS (
   SELECT t.startdate 'date'
     FROM TABLE t
    WHERE t.startdate = '1/1/2010'
   UNION ALL
   SELECT DATEADD(dd, 1, t.date) 
     FROM dates t
    WHERE DATEADD(dd, 1, t.date) <= (SELECT t.enddate FROM TABLE t WHERE t.enddate = '1/5/2010'))
SELECT ...
  FROM TABLE t
  JOIN dates d ON d.date = t.date
如果你的日期相隔不超过2047天:
SELECT DATEADD(day, 
               n.number, 
               (SELECT t.startdate FROM TABLE t WHERE t.startdate = '1/1/2010')
               )
  FROM (SELECT DISTINCT number 
          FROM MASTER.dbo.SPT_VALUES
         WHERE name IS NULL) n
 WHERE DATEADD(day, n.number, (SELECT t.startdate FROM TABLE t WHERE t.startdate = '1/1/2010')) <= (SELECT t.endate FROM TABLE t WHERE t.endate = '1/5/2010')

使用递归CTE生成序列:有害。但是你列出了 spt_values 方法,所以我会给你打分。 - Aaronaught
@Aaronaught:递归CTE比使用NUMBERS表技巧稍微更有效。不清楚SPT_VALUES。 - OMG Ponies
@Aaronaught:为什么它是邪恶的 - 尾递归只是一个循环。 - Hogan
@Hogan:尾递归可以被转换为循环,但这并不意味着它总是被转换。设置OPTION (MAXRECURSION 10)(或类似的选项)将导致此操作失败,这至少说明它实际上是通过递归执行的。 - Aaronaught

0
with DateList as 
( 
      select cast('1/1/2010' as datetime) DateValue 
      union all 
      select DateValue + 1 
      from    DateList     
      where   DateValue + 1 >= '1/1/2010' AND DateValue +1 <= '1/5/2010' 
) 
select CONVERT(varchar, DateValue, 101) 
from    DateList 

OPTION (MAXRECURSION 0) 

2
他想要的不是表格中的日期,而是开始日期和结束日期之间的所有日历日期列表。 - Russell Steen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,