获取SQL Server中所有日期的两个日期之间的所有日期

时间:2017-10-16 12:41:04

标签: sql-server

我必须生成一个SQL查询的结果集,该结果集应与以下内容匹配,但让我解释输入和输出:

我有一个名为Orders的表,这个表在某些时间有几个小时的订单,然后,我被要求提供一个结果集,该结果集应该可以获得两个日期之间的所有日期(即2017-10-01和2017-10-07),每天24小时,即使那天或那个小时没有订单,但它应该以{{1​​}}值出现。

0

因此,上述结果集应该包含给定两个日期之间的每一天,并且每天应该全部24小时,无论当天有订单和小时相同(无论是否有订单)

3 个答案:

答案 0 :(得分:1)

最简单的方法是使用临时表或表变量来填充所需的结果集,然后计算每行的订单数。

declare @Date1 date = '2017-10-01';
declare @Date2 date = '2017-10-07';
declare @Hour int;
declare @Period table (Day Date, Hour Time);

while @Date1 <= @Date2
begin
  set @Hour = 0;
  while @Hour < 24
  begin
    insert into @Period (Day, Hour) values (@Date1, TimeFromParts(@Hour,0,0,0,0));
    set @Hour = @Hour + 1; 
  end
  set @Date1 = DateAdd(Day, 1, @Date1);
end

select Day, Hour, 
       (select count(*) 
        from Orders
        where Orders.Day = Period.Day and Orders.Hour = Period.Hour) as TotalOrders
from @Period as Period;

答案 1 :(得分:1)

我更喜欢使用计数表而不是使用循环。性能要好得多。我保持对我的系统的统计,就像这样的观点。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    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
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

现在我们有了计数表,我们可以使用一些基本的数学来获得所需的输出。这些方面的东西。

declare @Date1 datetime = '2017-10-01';
declare @Date2 datetime = '2017-10-07';

select Day = convert(date, DATEADD(hour, t.N, @Date1))
    , Hour = t.N - 1
    , TotalOrders = COUNT(o.OrderID)
from cteTally t
left join Orders o on o.OrderDate = DATEADD(hour, t.N, @Date1)
where t.N <= DATEDIFF(hour, @Date1, @Date2)
group by DATEDIFF(hour, @Date1, @Date2)
    , t.N

答案 2 :(得分:1)

我是使用嵌套CTE完成的:

DECLARE @MinDate DATE = '20171001',
    @MaxDate DATE = '20171006';

 ;WITH INNER_CTE as(
SELECT  TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
    Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)
FROM    sys.all_objects a
    CROSS JOIN sys.all_objects b) ,

OUTER_CTE as (
select * from INNER_CTE 
cross apply (
SELECT TOP (24) n = ROW_NUMBER()  OVER (ORDER BY [object_id]) -1
FROM sys.all_objects ORDER BY n)) t4
 )

  select t1.Date, t1.n [Hour], ISNULL(t2.TotalORders,0) TotalOrders from 
  OUTER_CTE t1
 LEFT JOIN orders t2 on t1.Date = t2.[Day] and t1.n = t2.[Hour]

关于使用查询生成序列的好读物:https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1