表示与SQL Server表中的数据重叠计划的最佳方法

时间:2016-01-13 20:59:08

标签: sql sql-server sql-server-2008 tsql

我有一张表格,上面有医生的手术时间表信息。我在表格中有样本数据。 我试图从表中获取数据与额外的列,如overlapflag,overlap_percenatge。这是我在表格中的示例数据。

create table #Schedule_Test 
(SURG_ID INT , PAT_ID VARCHAR(10),DOC_ID VARCHAR(10),PROC_BEGIN DATETIME,PROC_END DATETIME)

INSERT INTO #Schedule_Test
VALUES(1, 'PAT-01' ,'DOC-01','2015-12-09 07:00:00.000','2015-12-09 07:30:00.000')
     ,(2, 'PAT-02' ,'DOC-01','2015-12-09 07:15:00.000','2015-12-09 07:45:00.000')
     ,(3, 'PAT-03' ,'DOC-01','2015-12-09 08:00:00.000','2015-12-09 08:30:00.000')
     ,(4, 'PAT-04' ,'DOC-01','2015-12-09 08:15:00.000','2015-12-09 08:45:00.000')
     ,(5, 'PAT-05' ,'DOC-01','2015-12-09 09:00:00.000','2015-12-09 09:30:00.000')
     ,(6, 'PAT-06' ,'DOC-01','2015-12-09 11:00:00.000','2015-12-09 12:30:00.000')
     ,(7, 'PAT-07' ,'DOC-01','2015-12-09 11:30:00.000','2015-12-09 12:00:00.000')

如果我们查看查询的结果集,surg-01从7:00开始并在7:30结束,其中surg-02开始befor surg-01结束,这意味着这是重叠过程。 而且,使用Surg-02时,sug-03并没有过度研磨,但是它已经超过了外科手术04。因此,如果任何手术在某一天与其他手术重叠,那么我应该将其标记为重叠。 凭借我的知识和其他博客的一些帮助,我得到了这个查询。

**( THIS QUERY WILL EXECUTE ONLY IN 2012 OR GREATER VERSION OF SQL SERVER)**


SELECT T.*,
CASE WHEN cat.PAT_ID IS NULL THEN 'N' ELSE 'Y' END AS Overlap_Flag,
CASE WHEN cat.PAT_ID IS NULL THEN '0' ELSE CONCAT(DATEDIFF(MINUTE,T.PROC_BEGIN,cat.PROC_END)/60,'H ',DATEDIFF(MINUTE,T.PROC_BEGIN,cat.PROC_END)%60,' MIN') END AS Overlap_Time
,cat.PAT_ID as Overlapping_with_PAT_ID
FROM #SCHEDULE_TEST T
OUTER APPLY
(  SELECT TOP 1 * 
   FROM #Schedule_Test 
   WHERE T.DOC_ID = DOC_ID 
   AND T.PROC_BEGIN > PROC_BEGIN 
   AND T.PROC_BEGIN < PROC_END
   ORDER BY PROC_BEGIN ) cat
这不是我想要的。这就是我想要的 计算新列的逻辑 如果程序之间存在重叠, Overlap_Flg 将为true(Y) overlap_percentage 将根据该患者的程序/总程序时间之间的重叠计算

SURG_ID PAT_ID  DOC_ID        PROC_BEGIN       PROC_END          Overlap_Flag   Overlap_percentage  Overlapping_with_PAT_ID
1   PAT-01  DOC-01  2015-12-09 07:00:00.000 2015-12-09 07:30:00.000    Y                    50%                  PAT_02
2   PAT-02  DOC-01  2015-12-09 07:15:00.000 2015-12-09 07:45:00.000    Y                    50%                  PAT-01
3   PAT-03  DOC-01  2015-12-09 08:00:00.000 2015-12-09 08:30:00.000    Y                    50%                  PAT-04
4   PAT-04  DOC-01  2015-12-09 08:15:00.000 2015-12-09 08:45:00.000    Y                    50%                  PAT-03
5   PAT-05  DOC-01  2015-12-09 09:00:00.000 2015-12-09 09:30:00.000    N                    0%                    NULL
6   PAT-06  DOC-01  2015-12-09 11:00:00.000 2015-12-09 12:30:00.000    Y                    50%                   PAT-07 
7   PAT-07  DOC-01  2015-12-09 11:30:00.000 2015-12-09 12:00:00.000    Y                    100%                      PAT-06 

任何帮助都将获得通过

2 个答案:

答案 0 :(得分:0)

如果两个日期重叠,有一种非常简单的方法可以比较。

Determine Whether Two Date Ranges Overlap

使用它可以将表连接到自身,以查找A是否与B重叠。

<强> SQL FIDDLE DEMO

SELECT ST1.*,
       CASE WHEN ST2.PAT_ID IS NULL THEN 'N' ELSE 'Y' END AS Overlap_Flag,
       CASE WHEN ST2.PAT_ID IS NULL THEN '0' 
            ELSE CONVERT(nvarchar(10),
                         CONVERT(numeric(10,2),
                            DATEDIFF(MINUTE, 
                                     CASE WHEN ST1.PROC_BEGIN < ST2.PROC_BEGIN 
                                          THEN ST2.PROC_BEGIN
                                          ELSE ST1.PROC_BEGIN
                                     END, 
                                     CASE WHEN ST1.PROC_END < ST2.PROC_END 
                                          THEN ST1.PROC_END
                                          ELSE ST2.PROC_END
                                     END                              
                                    ) * 100.0
                            /
                            DATEDIFF(MINUTE, ST1.PROC_BEGIN, ST1.PROC_END) 
                            )
                     ) + '%'
       END AS Overlap_Time,
       ST2.PAT_ID as Overlapping_with_PAT_ID
FROM Schedule_Test ST1
LEFT JOIN Schedule_Test ST2
       ON ST1.PROC_BEGIN <= ST2.PROC_END
      AND ST1.PROC_END >= ST2.PROC_BEGIN
      AND ST1.SURG_ID <> ST2.SURG_ID
      AND ST1.DOC_ID = ST2.DOC_ID

这将提供A是否与B重叠,但如果B与A重叠

输出

| SURG_ID | PAT_ID | DOC_ID |                 PROC_BEGIN |                   PROC_END | Overlap_Flag | Overlap_Time | Overlapping_with_PAT_ID |
|---------|--------|--------|----------------------------|----------------------------|--------------|--------------|-------------------------|
|       1 | PAT-01 | DOC-01 | December, 09 2015 07:00:00 | December, 09 2015 07:30:00 |            Y |       50.00% |                  PAT-02 |
|       2 | PAT-02 | DOC-01 | December, 09 2015 07:15:00 | December, 09 2015 07:45:00 |            Y |       50.00% |                  PAT-01 |
|       3 | PAT-03 | DOC-01 | December, 09 2015 08:00:00 | December, 09 2015 08:30:00 |            Y |       50.00% |                  PAT-04 |
|       4 | PAT-04 | DOC-01 | December, 09 2015 08:15:00 | December, 09 2015 08:45:00 |            Y |       50.00% |                  PAT-03 |
|       5 | PAT-05 | DOC-01 | December, 09 2015 09:00:00 | December, 09 2015 09:30:00 |            N |            0 |                  (null) |
|       6 | PAT-06 | DOC-01 | December, 09 2015 11:00:00 | December, 09 2015 12:30:00 |            Y |       33.33% |                  PAT-07 |
|       7 | PAT-07 | DOC-01 | December, 09 2015 11:30:00 | December, 09 2015 12:00:00 |            Y |      100.00% |                  PAT-06 |

如果用

替换最后一行,您可以修复它
      AND ST1.SURG_ID < ST2.SURG_ID

此外,我正在返回*您必须适应以返回您需要的格式,但看起来您已经知道如何做到这一点。

注意

  • 这项工作与旧的版本的SQL我在2008年测试它
  • 如果手术不与任何人重叠,将在最后一列返回null

答案 1 :(得分:0)

SELECT T.*,
       O.surdgID as O.surgID as Overlapping_surgID, 
       CASE WHEN O.surgID IS NULL THEN '0' 
            ELSE DATEDIFF(MINUTE, O.PROC_BEGIN, T.PROC_END) * 100 / DATEDIFF(Minute, T.PROC_BEGIN, O.PROC_END) 
       END AS Overlap_Pct
,cat.PAT_ID as Overlapping_with_PAT_ID
FROM #SCHEDULE_TEST T 
LEFT JOIN #SCHEDULE_TEST O
       on O.docID = t.docID 
      and O.surdID <> t.surdID  
      and T.PROC_END > O.PROC_BEGIN  
      and T.PROC_END < O.PROC_END  -- if in order I don't think you need this 
                                   -- and use O.surdID > t.surdID