[英]SQL: Get an aggregate (SUM) of a calculation of two fields (DATEDIFF) that has conditional logic (CASE WHEN)
I have a dataset that includes a bunch of stay data (at a hotel). 我有一个包含大量住宿数据的数据集(在酒店)。 Each row contains a start date and an end date, but no duration field.
每行包含开始日期和结束日期,但没有持续时间字段。 I need to get a sum of the durations.
我需要得到持续时间的总和。
Sample Data: 样本数据:
| 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 |
There are some added complications: 还有一些复杂的问题:
I'm not actually any good at SQL so all I have is guesswork. 我实际上并不擅长SQL,所以我只是猜测。
The proper syntax for a Crystal Reports SQL Expression is something like this: 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)
)
And that's giving me the correct value for a single row, if I wanted to do this: 如果我想这样做,这给了我一行的正确价值:
| 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 |
But I want to get the SUM of Duration per client, so I want this: 但我希望得到每个客户端的持续时间的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 |
I've tried to just wrap a SUM() around my CASE but that doesn't work: 我试图在我的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)
)
It gives me an error that the StayDateEnd is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 它给出了一个错误,即StayDateEnd在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。 But I don't even know what that means, so I'm not sure how to troubleshoot, or where to go from here.
但我甚至不知道这意味着什么,所以我不确定如何排除故障,或者从哪里开始。 And then the next step is to get the SUM by Client ID.
然后下一步是通过客户端ID获取SUM。
Any help would be greatly appreciated! 任何帮助将不胜感激!
You need a subquery for sum based on group by client_id and a join between you table the subquery eg: 您需要一个基于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
Although the explanation and data set are almost impossible to match, I think this is an approximation to what you want. 虽然解释和数据集几乎不可能匹配,但我认为这是你想要的近似值。
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 https://rextester.com/HCKOR53440
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.