两次之间的换档次数

时间:2019-02-24 00:50:29

标签: sql tsql sql-server-2012

能为您提供以下帮助吗?

我正在尝试计算患者在医院可能发生的转变。移位时间从7:00 AM6:59 PM,从7:00 PM6.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,但是查询花费了太多时间才能完成。有任何简单的计算时间的方法吗?

2 个答案:

答案 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_entereddate_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

Demo on dbfiddle