簡體   English   中英

SQL:獲取具有條件邏輯的兩個字段(DATEDIFF)的計算的聚合(SUM)(CASE WHEN)

[英]SQL: Get an aggregate (SUM) of a calculation of two fields (DATEDIFF) that has conditional logic (CASE WHEN)

我有一個包含大量住宿數據的數據集(在酒店)。 每行包含開始日期和結束日期,但沒有持續時間字段。 我需要得到持續時間的總和。

樣本數據:

| Stay ID | Client ID | Start Date | End Date   |
| 1       | 38        | 01/01/2018 | 01/31/2019 |
| 2       | 16        | 01/03/2019 | 01/07/2019 |
| 3       | 27        | 01/10/2019 | 01/12/2019 |
| 4       | 27        | 05/15/2019 | NULL       |
| 5       | 38        | 05/17/2019 | NULL       |

還有一些復雜的問題:

  1. 我正在使用Crystal Reports,這是一個SQL表達式,它遵循略有不同的規則。 基本上,它返回單個標量值。 以下是一些更多信息: http//www.cogniza.com/wordpress/2005/11/07/crystal-reports-using-sql-expression-fields/
  2. 有時,結束日期字段為空(他們尚未預訂)。 如果為空,我想用當前時間戳替換它。
  3. 我只想算一下去年發生的夜晚。 如果給定停留的開始日期超過一年,我需要調整它。
  4. 我需要通過客戶ID獲得一筆款項

我實際上並不擅長SQL,所以我只是猜測。

Crystal Reports SQL Expression的正確語法如下所示:

(
SELECT (CASE
WHEN StayDateStart < DATEADD(year,-1,CURRENT_TIMESTAMP) THEN DATEDIFF(day,DATEADD(year,-1,CURRENT_TIMESTAMP),ISNULL(StayDateEnd,CURRENT_TIMESTAMP))
ELSE DATEDIFF(day,StayDateStart,ISNULL(StayDateEnd,CURRENT_TIMESTAMP))
END)
)

如果我想這樣做,這給了我一行的正確價值:

| Stay ID | Client ID | Start Date | End Date   | Duration |
| 1       | 38        | 01/01/2018 | 01/31/2019 | 210      | // only days since June 4 2018 are counted
| 2       | 16        | 01/03/2019 | 01/07/2019 | 4        |
| 3       | 27        | 01/10/2019 | 01/12/2019 | 2        |
| 4       | 27        | 05/15/2019 | NULL       | 21       |
| 5       | 38        | 05/17/2019 | NULL       | 19       |

但我希望得到每個客戶端的持續時間的SUM,所以我想要這個:

| Stay ID | Client ID | Start Date | End Date   | Duration |
| 1       | 38        | 01/01/2018 | 01/31/2019 | 229      | // 210+19
| 2       | 16        | 01/03/2019 | 01/07/2019 | 4        |
| 3       | 27        | 01/10/2019 | 01/12/2019 | 23       | // 2+21
| 4       | 27        | 05/15/2019 | NULL       | 23       |
| 5       | 38        | 05/17/2019 | NULL       | 229      |

我試圖在我的CASE周圍包裝一個SUM(),但這不起作用:

(
SELECT SUM(CASE
WHEN StayDateStart < DATEADD(year,-1,CURRENT_TIMESTAMP) THEN DATEDIFF(day,DATEADD(year,-1,CURRENT_TIMESTAMP),ISNULL(StayDateEnd,CURRENT_TIMESTAMP))
ELSE DATEDIFF(day,StayDateStart,ISNULL(StayDateEnd,CURRENT_TIMESTAMP))
END)
)

它給出了一個錯誤,即StayDateEnd在選擇列表中無效,因為它不包含在聚合函數或GROUP BY子句中。 但我甚至不知道這意味着什么,所以我不確定如何排除故障,或者從哪里開始。 然后下一步是通過客戶端ID獲取SUM。

任何幫助將不勝感激!

您需要一個基於group by client_id的sum的子查詢以及表示子查詢之間的連接,例如:

select  Stay_id, client_id, Start_date, End_date,  t.sum_duration 
from your_table
inner join ( 
    select Client_id, 

    SUM(CASE
    WHEN StayDateStart < DATEADD(year,-1,CURRENT_TIMESTAMP) THEN DATEDIFF(day,DATEADD(year,-1,CURRENT_TIMESTAMP),ISNULL(StayDateEnd,CURRENT_TIMESTAMP))
    ELSE DATEDIFF(day,StayDateStart,ISNULL(StayDateEnd,CURRENT_TIMESTAMP))
    END) sum_duration 

    from your_table  
    group by Client_id 
    ) t on t.Client_id = your_table.client_id

雖然解釋和數據集幾乎不可能匹配,但我認為這是你想要的近似值。

declare @your_data table (StayId int, ClientId int, StartDate date, EndDate date)
insert into @your_data values
(1,38,'2018-01-01','2019-01-31'),
(2,16,'2019-01-03','2019-01-07'),
(3,27,'2019-01-10','2019-01-12'),
(4,27,'2019-05-15',NULL),
(5,38,'2019-05-17',NULL)

;with data as (
  select *,
    datediff(day,
      case 
        when datediff(day,StartDate,getdate())>365 then dateadd(year,-1,getdate())
        else StartDate
      end,
      isnull(EndDate,getdate())
    ) days
  from @your_data
)
select *,
  sum(days) over (partition by ClientId)
from data

https://rextester.com/HCKOR53440

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM