2017-10-16 169 views
0

我必須生成結果集的SQL查詢應符合以下的,但讓我解釋一下投入和產出:獲取兩個日期之間的所有天在SQL Server整天小時

我有一個表名稱爲Orders,並且此表格在某些時間的某些日期有一些訂單,那麼我被要求提供一個結果集,該結果集應該獲得兩個日期(即2017-10-01和2017-10-07)之間的所有日期,,即使當天或那一小時沒有訂單,但每天應該會顯示0的值,而且每天都是24小時。

+------------+------+-------------+ 
| Day  | Hour | TotalOrders | 
+------------+------+-------------+ 
| 2017-10-01 | 0 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 1 |  3  | 
+------------+------+-------------+ 
| 2017-10-01 | 2 |  4  | 
+------------+------+-------------+ 
| 2017-10-01 | 3 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 4 |  7  | 
+------------+------+-------------+ 
| 2017-10-01 | 5 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 6 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 7 |  9  | 
+------------+------+-------------+ 
| 2017-10-01 | 8 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 9 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 10 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 11 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 12 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 13 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 14 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 15 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 16 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 17 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 18 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 19 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 20 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 21 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 22 |  0  | 
+------------+------+-------------+ 
| 2017-10-01 | 23 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 0 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 1 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 2 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 3 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 4 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 5 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 6 |  0  | 
+------------+------+-------------+ 
| 2017-10-02 | 7 |  0  | 
+------------+------+-------------+ 
| and so on .................. | 
+------------+------+-------------+ 

所以,上面的結果集應包含每天給定的兩個日期之間,並且每天應該都24小時,不論關閉的那一天已接到命令,與同爲小時(無論它有訂單或不)

回答

1

我做到了使用嵌套CTE:https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

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] 

瞭解使用查詢生成序列良好的閱讀

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

我更喜歡用理貨表而不是使用循環來做到這一點。性能要好得多。作爲一個這樣的觀點,我保留在我的系統上。

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 
相關問題