能为您提供以下帮助吗?
我正在尝试计算患者在医院可能发生的转变。移位时间从7:00 AM
到6:59 PM
,从7:00 PM
到6.59 AM
。
如果轮班开始后患者被送往某个地点,我们将在总计算中忽略该轮班。
以下是示例数据以及最终结果应如何:
DECLARE @T AS TABLE
(
ID INT,
LOCATION VARCHAR(10),
Date_entered DATETIME,
date_left datetime
);
DECLARE @endresult AS TABLE
(
ID INT,
LOCATION VARCHAR(10),
Date_entered DATETIME,
date_left datetime,
Total_shifts int
)
insert into @T VALUES
(1,'AB','01/01/2019 07:10','01/01/2019 20:30'),
(2,'CD','01/01/2019 20:30','01/04/2019 02:30'),
(3,'EF','01/04/2019 02:30','01/07/2019 19:30'),
(4,'GH','01/07/2019 19:30','01/08/2019 13:30')
insert into @endresult VALUES
(1,'AB','01/01/2019 07:10','01/01/2019 20:30',1),
(2,'CD','01/01/2019 20:30','01/04/2019 02:30',4),
(3,'EF','01/04/2019 02:30','01/07/2019 19:30',8),
(4,'GH','01/07/2019 19:30','01/08/2019 13:30',1)
SELECT * FROM @t
select * from @endresult
我尝试使用递归CTE,但是查询花费了太多时间才能完成。有任何简单的计算时间的方法吗?
答案 0 :(得分:2)
这是一个查询,可为您的样本数据返回正确的结果:
select
t.*,
DATEDIFF(DAY, date_entered, date_left) * 2
- CASE WHEN DATEPART(HOUR, date_entered) < 7 THEN 0 WHEN DATEPART(HOUR, date_entered) < 19 THEN 1 ELSE 2 END
+ CASE WHEN DATEPART(HOUR, date_left) < 7 THEN 0 WHEN DATEPART(HOUR, date_left) < 19 THEN 1 ELSE 2 END
AS Total_shifts
from @t t;
逻辑是先计算出入口之间有多少天,然后将其乘以2得到原始的班次数;然后通过检查患者进入和离开的时间来调整原始计数。
此 demo on DB Fiddle 及其示例数据将返回:
ID | LOCATION | Date_entered | date_left | Total_shifts -: | :------- | :------------------ | :------------------ | -----------: 1 | AB | 01/01/2019 07:10:00 | 01/01/2019 20:30:00 | 1 2 | CD | 01/01/2019 20:30:00 | 04/01/2019 02:30:00 | 4 3 | EF | 04/01/2019 02:30:00 | 07/01/2019 19:30:00 | 8 4 | GH | 07/01/2019 19:30:00 | 08/01/2019 13:30:00 | 1
答案 1 :(得分:1)
这是一个查询,它将为您提供所需的结果。它使用3个CTE,第一个仅选择最小Date_entered
和最大date_left
值,第二个将最小Date_entered
值与换档开始时间(上午7点或晚上7点)对齐,第三个递归CTE生成最小Date_entered
和最大date_left
值之间的所有换档开始时间的列表。最后,我们将CTE加入到准入表中,并计算Date_entered
和date_left
之间的换班开始时间:
WITH cte AS
(SELECT MIN(Date_entered) AS min_date, MAX(date_left) AS max_date
FROM T),
cte1 AS
(SELECT CASE WHEN DATEPART(hour, min_date) < 7 THEN DATEADD(hour, 19, DATEADD(day, -1, CONVERT(DATE, min_date)))
ELSE DATEADD(hour, 7, CONVERT(DATETIME, CONVERT(DATE, min_date)))
END AS min_shift
FROM cte),
shifts AS
(SELECT min_shift AS shift_start
FROM cte1
UNION ALL
SELECT DATEADD(hour, 12, shift_start)
FROM shifts
WHERE shift_start < (SELECT max_date FROM cte))
SELECT T.ID, T.LOCATION, T.Date_Entered, T.date_left, COUNT(s.shift_start) AS Total_shifts
FROM T
JOIN shifts s ON s.shift_start BETWEEN T.Date_Entered AND T.date_left
GROUP BY T.ID, T.LOCATION, T.Date_Entered, T.date_left
输出:
ID LOCATION Date_Entered date_left Total_shifts
1 AB 01/01/2019 07:10:00 01/01/2019 20:30:00 1
2 CD 01/01/2019 20:30:00 04/01/2019 06:59:00 4
3 EF 04/01/2019 07:00:00 07/01/2019 19:30:00 8
4 GH 07/01/2019 19:30:00 08/01/2019 13:30:00 1