0

単純なクエリの場合、非常に多くの副選択とWITHステートメントを書き出さなければならないのは気になります。

問題は、サブクエリを持つクエリを単純化する方法に関する基本的なガイドラインはありますか?

これが私の質問です:

WITH cte_min
     AS (SELECT a.client_id,
                a.specimen_source,
                a.received_date
         FROM   f_accession_daily a
                JOIN (SELECT DISTINCT f.client_id,
                                      f.received_date,
                                      f.accession_daily_key
                      FROM   F_ACCESSION_DAILY f
                             JOIN (SELECT CLIENT_ID,
                                          Min(received_date) MinRecDate
                                   FROM   F_ACCESSION_DAILY
                                   GROUP  BY CLIENT_ID) i
                               ON f.CLIENT_ID = i.CLIENT_ID
                                  AND f.RECEIVED_DATE = i.MinRecDate) b
                  ON a.ACCESSION_DAILY_KEY = b.ACCESSION_DAILY_KEY),
     cte_max
     AS (SELECT a.client_id,
                a.specimen_source,
                a.received_date
         FROM   f_accession_daily a
                JOIN (SELECT DISTINCT f.client_id,
                                      f.received_date,
                                      f.accession_daily_key
                      FROM   F_ACCESSION_DAILY f
                             JOIN (SELECT CLIENT_ID,
                                          Max(received_date) MaxRecDate
                                   FROM   F_ACCESSION_DAILY
                                   GROUP  BY CLIENT_ID) i
                               ON f.CLIENT_ID = i.CLIENT_ID
                                  AND f.RECEIVED_DATE = i.MaxRecDate) b
                  ON a.ACCESSION_DAILY_KEY = b.ACCESSION_DAILY_KEY),
     cte_est
     AS (SELECT DISTINCT client_id,
                         MLIS_DATE_ESTABLISHED
         FROM   D_CLIENT
         WHERE  REC_ACTIVE_FLG = 1
                AND MLIS_DATE_ESTABLISHED IS NOT NULL)
SELECT DISTINCT f.client_id,
                cmin.specimen_source,
                cmin.received_date,
                cmax.specimen_source,
                cmax.received_date,
                cest.MLIS_DATE_ESTABLISHED
FROM   F_ACCESSION_DAILY f
       LEFT JOIN cte_max cmax
         ON cmax.CLIENT_ID = f.CLIENT_ID
       LEFT JOIN cte_min cmin
         ON cmin.CLIENT_ID = f.CLIENT_ID
       LEFT JOIN cte_est cest
         ON cest.CLIENT_ID = f.CLIENT_ID 

私は必ずしもあなた自身が単純化することを求めているのではなく(私はこれに非常に感謝しますが)、むしろこのクエリをよりエレガントに書き直すための一般的なガイドライン/指示を求めています。

4

3 に答える 3

3

これはもっと良く見えますか?

;WITH minmax AS (
SELECT client_id, specimen_source, received_date,
       RMin = row_number() over (partition by Client_id
                                 order by received_date, accession_daily_key),
       RMax = row_number() over (partition by Client_id
                                 order by received_date desc, accession_daily_key desc)
FROM F_ACCESSION_DAILY
)
SELECT f.client_id,
       max(case when rmin=1 then f.specimen_source end),
       max(case when rmin=1 then f.received_date end),
       max(case when rmax=1 then f.specimen_source end),
       max(case when rmax=1 then f.received_date end),
       D.MLIS_DATE_ESTABLISHED
FROM   minmax f
LEFT JOIN D_CLIENT D ON D.REC_ACTIVE_FLG = 1 AND D.MLIS_DATE_ESTABLISHED IS NOT NULL
WHERE 1 in (f.rmin, f.rmax)
GROUP BY f.client_id, D.MLIS_DATE_ESTABLISHED
于 2012-09-25T21:33:10.500 に答える
1

5つの値を報告する50行で、そのすべてで2つのテーブルのみが参照されます。

最初のCTEには、同じテーブルへの4つの結合(または仮想結合)があり、3つの列のレポートに関係する他のテーブルはありません。キーがわからないので、減らすことができると結論付けることはできません。

cteが複数回参照されていない場合、コード行が少なくなることはありません。

1つは、このcteをより少ないコードに置き換えることができます。

cte_est
     AS (SELECT DISTINCT client_id,
                         MLIS_DATE_ESTABLISHED
         FROM   D_CLIENT
         WHERE  REC_ACTIVE_FLG = 1
                AND MLIS_DATE_ESTABLISHED IS NOT NULL)
...
cest.MLIS_DATE_ESTABLISHED
...
LEFT JOIN cte_est cest
         ON cest.CLIENT_ID = f.CLIENT_ID

に減少します

D_CLIENT.MLIS_DATE_ESTABLISHED
...
LEFT JOIN  D_CLIENT 
       ON  D_CLIENT.CLIENT_ID = f.CLIENT_ID 
       AND D_CLIENT.REC_ACTIVE_FLG = 1
       AND D_CLIENT.MLIS_DATE_ESTABLISHED IS NOT NULL
于 2012-09-25T20:06:35.437 に答える
1

誰もがこれをより単純で読みやすいと考えるかどうかはわかりませんが、これが私が行う方法です。

WITH 
  cte_MaxMinRecvd As
(
    SELECT      CLIENT_ID,   
                Min(received_date) MinRecDate,
                Max(received_date) MaxRecDate
    FROM        F_ACCESSION_DAILY
    GROUP BY    CLIENT_ID
)
, cte_MaxMinDaily As
(
    SELECT      *
    FROM        F_ACCESSION_DAILY f
    JOIN        cte_MaxMinRecvd   i     ON  f.CLIENT_ID = i.CLIENT_ID
)
, cte_min AS 
(
    SELECT  a.client_id,
            a.specimen_source,
            a.received_date
    FROM    F_ACCESSION_DAILY a
    WHERE   EXISTS(
                    SELECT  *
                    FROM    cte_MaxMinDaily f
                    WHERE   f.RECEIVED_DATE       = f.MinRecDate
                      AND   a.ACCESSION_DAILY_KEY = f.ACCESSION_DAILY_KEY
                   )
)
, cte_max AS 
(
    SELECT  a.client_id,
            a.specimen_source,
            a.received_date
    FROM    f_accession_daily a
    WHERE   EXISTS(
                    SELECT  *
                    FROM    cte_MaxMinDaily f
                    WHERE   f.RECEIVED_DATE       = f.MinRecDate
                      AND   a.ACCESSION_DAILY_KEY = f.ACCESSION_DAILY_KEY
                   )
)
SELECT DISTINCT 
            f.client_id,
            cmin.specimen_source,
            cmin.received_date,
            cmax.specimen_source,
            cmax.received_date,
            cest.MLIS_DATE_ESTABLISHED
FROM        F_ACCESSION_DAILY f
LEFT JOIN   cte_max  cmax        ON  cmax.CLIENT_ID = f.CLIENT_ID
LEFT JOIN   cte_min  cmin        ON  cmin.CLIENT_ID = f.CLIENT_ID
LEFT JOIN   D_CLIENT cest        ON  cest.CLIENT_ID = f.CLIENT_ID 
                                 AND cest.REC_ACTIVE_FLG = 1
                                 AND cest.MLIS_DATE_ESTABLISHED IS NOT NULL

主に私がしたことは

  1. 該当する場合は、ほとんどのサブクエリをCTEに変換します。
  2. 最小サブクエリと最大サブクエリをマージし、
  3. DISTINCTサブクエリをEXISTSサブクエリに変更します。これは、より単純にすることができます(通常はパフォーマンスが向上します)。

おっと、Blamが提案したように私もcte_estCTEを取り除きました。

于 2012-09-25T21:10:13.383 に答える