0

私はSQL Server 2008を使用していますが、下のクエリの速度を上げようとしています。照会は、再入日に基づいて患者にポイントを割り当てる。SQL:CTEクエリの速度

例:患者は、1/2,1/5,1/7,1/8,1/9,2/4で見られます。私はお互いの3日以内に最初に訪問をグループ化したいです。 1/2-5がグループ化され、1/7-9がグループ化されます。 1/5の実際の訪問日が1/2であるため、1/5は1/7とグループ化されません。 1/7は1/2からの再送信であるため3点を受け取る。 1/7からの再送信であるため、2/4は3点も受信します。日付がグループ化されると、最初の日付が実際の訪問日となります。

ほとんどの記事は、データセットを制限したり、インデックスを追加して速度を上げることを推奨しています。私は約15,000に行の量を制限し、インデックスを追加しました。 45回のテスト訪問日/ 3人のテスト患者でクエリを実行すると、クエリの実行には1.5分かかります。私の実際のデータセットでは、8時間以上かかります。 1時間に<を実行するには、このクエリを取得するにはどうすればよいですか?私の質問を書く良い方法はありますか?私のインデックスは正しいか?どんな助けでも大歓迎です。

クエリの下に期待される結果の例。

;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 
+0

あなたはあなたに何を記述する必要があります(

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 

が VisitDate 、MRN 、NextDay 、1 OrderRow AS A1 FROM SELECT)ASサンプルデータと望ましい結果を含めて、しようとしています。 –

+1

また、codereview.stackexchange.comのサイト – scsimon

+0

にこれを投稿することをお勧めします。 – JBritton

答えて

1

はおっと私はいくつかのCTEの名前を変更(およびポストは何であったかめちゃめちゃコード)

それはこのようにする必要があります:

B

+3

修正のために新しい回答を追加するのではなく、元の回答を編集してください。 –

+0

ありがとうIvan。 <10秒で実行されます。テストの後、私もRiskReadmits.MRN = Z1.MRNをaのサブクエリに設定する必要がありました。 – JBritton

0

私はここに野生の推測を取るつもり、あなたが二通り 持ち、a.MRN = b.MRNにBのCTEを変更したいと言っていますこのような第2の選択クエリ内の条件は:

, 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 
)