【问题标题】:SQL: CTE query SpeedSQL:CTE 查询速度
【发布时间】:2016-10-05 11:43:00
【问题描述】:

我正在使用 SQL Server 2008 并试图提高下面查询的速度。该查询根据再入院日期为患者分配积分。

示例:患者于 1/2、1/5、1/7、1/8、1/9、2/4 就诊。我想在 3 天内进行第一次团体访问。 1/2-5分组,1/7-9分组。 1/5 不与 1/7 分组,因为 1/5 的实际访问日期是 1/2。 1/7 将获得 3 分,因为它是 1/2 的重新录取。 2/4 也将获得 3 分,因为它是 1/7 的重新录取。当日期分组时,第一个日期是实际访问日期。

大多数文章建议限制数据集或添加索引以提高速度。我将行数限制在 15,000 左右并添加了一个索引。当运行具有 45 个测试访问日期/3 个测试患者的查询时,查询需要 1.5 分钟才能运行。使用我的实际数据集需要 > 8 小时。 我怎样才能让这个查询运行

查询下方的示例预期结果。

;CREATE TABLE RiskReadmits(MRN INT, VisitDate DATE, Category VARCHAR(15))
;CREATE CLUSTERED INDEX Risk_Readmits_Index ON RiskReadmits(VisitDate)

;INSERT RiskReadmits(MRN,VisitDate,CATEGORY)
VALUES
(1, '1/2/2016','Inpatient'),
(1, '1/5/2016','Inpatient'),  
(1, '1/7/2016','Inpatient'),  
(1, '1/8/2016','Inpatient'), 
(1, '1/9/2016','Inpatient'),  
(1, '2/4/2016','Inpatient'), 
(1, '6/2/2016','Inpatient'),
(1, '6/3/2016','Inpatient'),
(1, '6/5/2016','Inpatient'),  
(1, '6/6/2016','Inpatient'), 
(1, '6/8/2016','Inpatient'),  
(1, '7/1/2016','Inpatient'),  
(1, '8/1/2016','Inpatient'),  
(1, '8/4/2016','Inpatient'),  
(1, '8/15/2016','Inpatient'), 
(1, '8/18/2016','Inpatient'), 
(1, '8/28/2016','Inpatient'),
(1, '10/12/2016','Inpatient'),
(1, '10/15/2016','Inpatient'),
(1, '11/17/2016','Inpatient'),
(1, '12/20/2016','Inpatient')

;WITH a AS (
    SELECT
          z1.VisitDate
        , z1.MRN
        , (SELECT MIN(VisitDate) FROM  RiskReadmits WHERE VisitDate > DATEADD(day, 3, z1.VisitDate)) AS NextDay
    FROM
        RiskReadmits z1 
    WHERE
        CATEGORY = 'Inpatient'
), a1 AS ( 
    SELECT
          MRN
        , MIN(VisitDate) AS VisitDate
        , MIN(NextDay) AS NextDay
    FROM
        a
    GROUP BY
        MRN
), b AS (
    SELECT
          VisitDate
        , MRN
        , NextDay
        , 1 AS OrderRow
    FROM
        a1

    UNION ALL

    SELECT
          a.VisitDate
        , a.MRN
        , a.NextDay
        , b.OrderRow +1 AS OrderRow
    FROM
        a
        JOIN b
        ON a.VisitDate = b.NextDay
), c AS (
SELECT
    MRN,
    VisitDate
    , (SELECT MAX(VisitDate) FROM b WHERE b1.VisitDate > VisitDate AND b.MRN = b1.MRN) AS PreviousVisitDate 
FROM
    b b1
)
SELECT distinct
    c1.MRN,
    c1.VisitDate
    , CASE 
        WHEN DATEDIFF(day,c1.PreviousVisitDate,c1.VisitDate) < 30 THEN PreviousVisitDate
        ELSE NULL
     END AS ReAdmissionFrom
    , CASE
        WHEN DATEDIFF(day,c1.PreviousVisitDate,c1.VisitDate) < 30 THEN 3
        ELSE 0
    END AS Points
FROM
    c c1
ORDER BY c1.MRN

预期结果:

MRN VisitDate   ReAdmissionFrom Points
1   2016-01-02  NULL            0
1   2016-01-07  2016-01-02      3
1   2016-02-04  2016-01-07      3
1   2016-06-02  NULL            0
1   2016-06-06  2016-06-02      3
1   2016-07-01  2016-06-06      3
1   2016-08-01  NULL            0
1   2016-08-15  2016-08-01      3
1   2016-08-28  2016-08-15      3
1   2016-10-12  NULL            0
1   2016-11-17  NULL            0
1   2016-12-20  NULL            0

【问题讨论】:

  • 您应该描述您正在尝试做的事情,包括样本数据和期望的结果。
  • 我还建议您将其发布到 codereview.stackexchange.com 站点
  • 我继续发布了我的预期结果。
  • 如果1日、3日、4日有访问怎么办?您将其视为 1 日的访问,忽略 3 日的访问,然后在 4 日重新入院。但是为什么不能一号就诊,三号再入院呢?如果您可以可靠地确认某些访问被忽略的原因的业务逻辑,那么肯定有更快的方法来编写您的查询。

标签: sql sql-server recursion common-table-expression recursive-query


【解决方案1】:

哎呀,我改了几个 cte 的名字(帖子把代码搞砸了)

应该是这样的:

b AS ( 选择 访问日期 , 核磁共振 , 明天 , 1 作为 OrderRow 从 a1

UNION ALL

SELECT
      a.VisitDate
    , a.MRN
    , a.NextDay
    , b.OrderRow +1 AS OrderRow
FROM
    a AS a
    JOIN b
    ON a.VisitDate = b.NextDay AND a.MRN = b.MRN

)

【讨论】:

  • 请编辑您的原始答案,而不是添加新答案进行更正。
  • 谢谢伊万。它现在可以在
【解决方案2】:

我要在这里大胆猜测一下,说您想将 b cte 更改为 将 AND a.MRN = b.MRN 作为第二个选择查询中的第二个条件,如下所示:

, b AS (
    SELECT
          VisitDate
        , MRN
        , NextDay
        , 1 AS OrderRow
    FROM
        firstVisitAndFollowUp

    UNION ALL

    SELECT
          a.VisitDate
        , a.MRN
        , a.NextDay
        , b.OrderRow +1 AS OrderRow
    FROM
        visitsDistance3daysOrMore AS a
        JOIN b
        ON a.VisitDate = b.NextDay AND a.MRN = b.MRN
)

【讨论】:

    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多