【问题标题】:better way to generate months/year table生成月/年表的更好方法
【发布时间】:2014-01-17 15:19:25
【问题描述】:

我又开始使用更多的 tsql。有没有比下面更好的方法来生成一个表格,其中包含给定开始和结束日期的月份和年份整数?

DECLARE @FromDate DATETIME, @ToDate DATETIME
SET @FromDate = '2012-01-01 00:00:00.000'
SET @ToDate = '2012-31-12 23:59:59.000'

DECLARE @MonthsAndYears table (Month INT, Year int)

;WITH dates AS 
(
    SELECT @FromDate 'date'
        UNION ALL
    SELECT DATEADD(dd, 1, t.date) 
        FROM dates t
    WHERE DATEADD(dd, 1, t.date) <= @ToDate
)
INSERT INTO @MonthsAndYears
SELECT 
    DATEPART(MONTH, date),
    DATEPART(YEAR, date)
FROM dates 
GROUP BY 
DATEPART(MONTH, date),
DATEPART(YEAR, date)
option (maxrecursion 0)

【问题讨论】:

  • 小心2012-31-12之类的东西,也不要费心将时间设置为午夜前一分钟......
  • 在这种情况下 - 可能是一个愚蠢的问题 - 00:00:00.000 是一天的开始还是结束?
  • 00:00:00.000 是午夜 - 一天的开始。

标签: sql-server tsql sql-server-2005


【解决方案1】:

我更喜欢使用已经存在的集合,因为这通常比昂贵的递归 CTE 更有效。如果您有数字表,请使用它;如果您已经有日历表,那就更好了;否则,您可以使用内置对象,例如 master.dbo.spt_values:

DECLARE @FromDate DATETIME, @ToDate DATETIME;
SET @FromDate = '2012-01-01';
SET @ToDate = '2012-12-31';

-- all days in that period
SELECT TOP (DATEDIFF(DAY, @FromDate, @ToDate)+1) 
  TheDate = DATEADD(DAY, number, @FromDate)
  FROM [master].dbo.spt_values 
  WHERE [type] = N'P' ORDER BY number;

-- just the months in that period
SELECT TOP (DATEDIFF(MONTH, @FromDate, @ToDate)+1) 
  TheDate  = DATEADD(MONTH, number, @FromDate),
  TheMonth = MONTH(DATEADD(MONTH, number, @FromDate)),
  TheYear  = YEAR(DATEADD(MONTH, number, @FromDate))
  FROM [master].dbo.spt_values 
  WHERE [type] = N'P' ORDER BY number;

有关一些背景,请参阅:

【讨论】:

  • 谢谢。关于这一切,我用谷歌搜索了一下,发现了 master.dbo.spt_values 但不确定。谢谢!
  • @csetzkorn 数字表肯定更好,但不是每个人都想出于各种原因创建一个,也不是每个人都能做到。
猜你喜欢
  • 2020-04-20
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多