如何选择两个日期之间的所有小时?

10
declare @minDateTime as datetime;
declare @maxDateTime as datetime;

set @minDateTime = '2014-01-13 02:00:00';
set @maxDateTime = '2014-12-31 14:00:00';
我希望创建一个select语句,它可以返回@minDateTime和@maxDateTime之间的每个小时,如下所示(没有要选择的表格,我不想要where子句!):
2014-01-13 02:00:00
2014-01-13 03:00:00
2014-01-13 04:00:00
...
2014-12-31 12:00:00
2014-12-31 13:00:00
2014-12-31 14:00:00

所以你需要在Sql中完成这个任务而不是在C#中,这其中一定有很好的理由吧? - Kirk Woll
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
@JohnSaunders 我又学到了新的东西。谢谢 ;) - Marc
2个回答

17

试试这个。使用 递归CTE

DECLARE @minDateTime AS DATETIME;
DECLARE @maxDateTime AS DATETIME;

SET @minDateTime = '2014-01-13 02:00:00';
SET @maxDateTime = '2014-12-31 14:00:00';

;
WITH Dates_CTE
     AS (SELECT @minDateTime AS Dates
         UNION ALL
         SELECT Dateadd(hh, 1, Dates)
         FROM   Dates_CTE
         WHERE  Dates < @maxDateTime)
SELECT *
FROM   Dates_CTE
OPTION (MAXRECURSION 0) 
在上述查询中,Dates_CTE 是一个公共表达式表CTE 的基础记录由第一个SQL查询推导而来,在 UNION ALL 之前。查询的结果给出了你最小日期。 在UNION ALL之后执行的第二个查询将被重复执行以获得结果。这个过程是递归的,并将继续直到日期小于@maxDateTime

你好。我收到了以下信息:语句已终止。在语句完成之前,递归的最大深度100已经耗尽。 - Marc
@Marc - 我的错,现在检查一下。 - Pரதீப்
太棒了 :) 非常感谢! - Marc

2

以下是使用Tally Table的另一种方法:

DECLARE @minDateTime DATETIME;
DECLARE @maxDateTime DATETIME;

SET @minDateTime = '2014-01-13 02:00:00';
SET @maxDateTime = '2014-12-31 14:00:00';

DECLARE @hrsDiff INT;
SELECT @hrsDiff = DATEDIFF(HH, @minDateTime, @maxDateTime);

WITH E1(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
),--10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
Tally(N) AS(SELECT row_number() over(order by (select null)) from E4) -- Numbered rrow
SELECT @minDateTime 
UNION ALL
SELECT DATEADD(HH, N, @minDateTime)
FROM Tally
WHERE
    N <= @hrsDiff

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