2016-11-08 8 views
1

SQLに関しては、私は比較的経験がありません。私はCROSS APPLYを使用しているのだろうか?CROSSが最良の方法、またはEXISTSまたはサブクエリの場合は適用されますか?

私も仕事を複製していると思います。これは動作し、数分かかりますが、私の気持ちは良いことです。

私が見ている3つのメインテーブルは非常に大きく、それぞれ独自の数百万行を見ています。個々の挿入ステートメントは、それぞれ7〜15K行を戻しています。


DECLARE @Master TABLE 
    (
    heyno    NVARCHAR(12), 
    postcodestartdttm DATE, 
    postcodeenddttm DATE, 
    lzohistorypostcode NVARCHAR(25), 
    biactivitypostcode NVARCHAR(25), 
    activityenddttm DATE 
); 

INSERT INTO @Master 
SELECT p.pasid, 
     par.startdttm, 
     par.enddttm, 
     pa.postcode AS LZOHistoryPostcode, 
     t.postcode AS BIActivityPostcode, 
     t.admitdate 
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par 
     INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa 
       ON par.[addressoid] = pa.[oid] 
        AND pa.[status] = 'A' 
     INNER JOIN HEALTHBI.DBO.lzo_patient AS p 
       ON par.identifyingoid = p.oid 
     --- 
     CROSS APPLY (SELECT i.admitdate, 
          i.postcode 
        FROM HEALTHBI_VIEWS.DBO.ip_admission i 
        WHERE i.patientoid = p.oid 
          AND i.admitdate > par.startdttm 
          AND i.admitdate >= '01 APRIL 2010' 
          AND i.admitdate < ISNULL(par.enddttm, '31-dec-4712') 
          AND par.[status] = 'A' 
          AND par.[identifyingtype] = 'Patient' 
          AND par.[rotypcode] = 'CC_USUALADD' 
          AND pa.[adtypcode] = 'Address' 
          AND pa.postcode <> i.postcode) AS t 

INSERT INTO @Master 
SELECT p.pasid, 
     par.startdttm, 
     par.enddttm, 
     pa.postcode AS LZOHistoryPostcode, 
     t.postcode AS BIActivityPostcode, 
     t.apptstartdate 
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par 
     INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa 
       ON par.[addressoid] = pa.[oid] 
        AND pa.[status] = 'A' 
     INNER JOIN HEALTHBI.DBO.lzo_patient AS p 
       ON par.identifyingoid = p.oid 
     CROSS APPLY (SELECT i.apptstartdate, 
          i.postcode 
        FROM HEALTHBI_VIEWS.DBO.op_appointment i 
        WHERE i.patientoid = p.oid 
          AND i.apptstartdate > par.startdttm 
          AND i.apptstartdate >= '01 APRIL 2010' 
          AND i.apptstartdate < ISNULL(par.enddttm, '31-dec-4712') 
          AND par.[status] = 'A' 
          AND par.[identifyingtype] = 'Patient' 
          AND par.[rotypcode] = 'CC_USUALADD' 
          AND pa.[adtypcode] = 'Address' 
          AND pa.postcode <> i.postcode) AS t 

INSERT INTO @Master 
SELECT p.pasid, 
     par.startdttm, 
     par.enddttm, 
     pa.postcode AS LZOHistoryPostcode, 
     t.postcode AS BIActivityPostcode, 
     t.attenddate 
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par 
     INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa 
       ON par.[addressoid] = pa.[oid] 
        AND pa.[status] = 'A' 
     INNER JOIN HEALTHBI.DBO.lzo_patient AS p 
       ON par.identifyingoid = p.oid 
     CROSS APPLY (SELECT i.attenddate, 
          i.postcode 
        FROM HEALTHBI_VIEWS.DBO.ed_attendance i 
        WHERE i.patientoid = p.oid 
          AND i.attenddate > par.startdttm 
          AND i.attenddate >= '01 APRIL 2010' 
          AND i.attenddate < ISNULL(par.enddttm, '31-dec-4712') 
          AND par.[status] = 'A' 
          AND par.[identifyingtype] = 'Patient' 
          AND par.[rotypcode] = 'CC_USUALADD' 
          AND pa.[adtypcode] = 'Address' 
          AND pa.postcode <> i.postcode) AS t 

SELECT m.heyno, 
     m.lzohistorypostcode, 
     m.biactivitypostcode, 
     d.startofweek 
FROM @Master m 
     INNER JOIN HEALTHBI_VIEWS.DBO.date_reference AS d 
       ON m.activityenddttm = d.datevalue 
GROUP BY m.heyno, 
      m.lzohistorypostcode, 
      m.biactivitypostcode, 
      d.startofweek 
ORDER BY m.heyno 
+0

「LEFT JOIN」はなぜですか? – Ben

+0

メイン結合はPKに対して1-1です。 – Simon

+0

だから?それはどういう意味ですか? – Ben

答えて

-1

あなたはCROSSが適用使用する必要はありません。これは、テーブル値関数で使用するためのもので、カーソルのように動作します。一度に1つのレコードで、設定された操作よりもはるかに時間がかかります。

私は以下のようにOUTER JOINを使用しようとします。データをよりよく理解することなく正しく取得するのは難しいですが、患者ごとに複数の入学許可日とポストコードが表示されるようです。したがって、ip_addmissionビューが返す内容に応じて重複する可能性があります。それが望ましくない場合は、たとえばGROUP BYを使用して、最新の入会日のみを返すことができます。

また、WHERE句で関数を使用すると、テーブルスキャンが発生する可能性があります。私は以下のOR式でISNULLを置き換えました。

SELECT p.pasid, 
     par.startdttm, 
     par.enddttm, 
     pa.postcode AS LZOHistoryPostcode, 
     i.postcode AS BIActivityPostcode, 
     i.admitdate 
FROM HEALTHBI.DBO.[lzo_patientaddressrole] AS par 
     INNER JOIN HEALTHBI.DBO.[lzo_patientaddress] AS pa 
       ON par.[addressoid] = pa.[oid] 
        AND pa.[status] = 'A' 
     INNER JOIN HEALTHBI.DBO.lzo_patient AS p 
       ON par.identifyingoid = p.oid 
     --- 
     LEFT OUTER JOIN HEALTHBI_VIEWS.DBO.ip_admission i 
     ON i.patientoid = p.oid 

WHERE i.admitdate > par.startdttm 
          AND i.admitdate >= '01 APRIL 2010' 
          AND (i.admitdate < par.enddttm OR par.enddttm IS NULL) 
          AND par.[status] = 'A' 
          AND par.[identifyingtype] = 'Patient' 
          AND par.[rotypcode] = 'CC_USUALADD' 
          AND pa.[adtypcode] = 'Address' 
          AND pa.postcode <> i.postcode; 
+0

あなたはこれについて間違っています: "クロスアプライはテーブル値関数で使用するためのもので、カーソルのように動作します。 APPLYはJOINと同じくらい速く動作します。 –

関連する問題