1

孤立した ENI_MONITOR のすべてのレコードを取得したい。ENI_FLUSSI_HUB には、対応するレコードが存在してはなりません。両方の定式化は正しいですか? 左外部結合はどのように考えますか?

SELECT /*+ PARALLEL (mon, 10) */
       COUNT(1)
FROM   B
WHERE  B.mon_flag_ann = 'N'
       AND NOT EXISTS
           (
               SELECT /*+  PARALLEL (c, 10)  */
                      1
               FROM   A
               WHERE  B.MON_ID_MESSAGGIO = A.flh_id_messaggio
                      AND B.MON_COD_TP_PROCESSO = A.flh_tipo_processo_cod
                      AND A.FLH_FLAG_ANN = 'N'
           );


SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
       COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM   B,
       A
WHERE  B.mon_flag_ann = 'N'
       AND B.MON_ID_MESSAGGIO = A.flh_id_messaggio(+)
       AND B.MON_COD_TP_PROCESSO = A.flh_tipo_processo_cod(+)
       AND A.FLH_FLAG_ANN(+) = 'N'
       AND A.flh_id_messaggio(+) IS NULL
4

2 に答える 2

1

おそらくコードが NULL の場合を除いて、この 2 つは機能的に同等です。SQL は記述言語であり、手続き型言語ではありません。構文は、(必ずしも) 処理がどのように行われているかではなく、結果セットを記述します。

このようなクエリを作成する方法は複数あります (not inバージョンを含む)。クエリがどのように実行されるかは、エンジンによって選択されたパスによって異なります。 ここにいくつかのオプションがあります。Google で検索すると、クエリのさまざまな形式に対する特定のパフォーマンス タイミングの例が他にもあります。

2 番目の構造は、外部結合クエリを記述するには適切な方法ではありません。推奨される構文は次のとおりです。

SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
       COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM   B left outer join
       A
       on B.MON_ID_MESSAGGIO = A.flh_id_messaggio and
          B.MON_COD_TP_PROCESSO = A.flh_tipo_processo_cod and
          A.FLH_FLAG_ANN = 'N'
WHERE  B.mon_flag_ann = 'N' and
       A.flh_id_messaggio IS NULL
于 2013-01-16T11:22:54.217 に答える
1

それらは異なりますが、Gordon Linoff が示したように、ASNSI 結合構文に変換すると理由がわかりやすくなります。その形式では、2 番目のクエリは次のようになります。

SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
       COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM   B
LEFT JOIN A
    ON A.flh_id_messaggio = B.MON_ID_MESSAGGIO
    AND A.flh_tipo_processo_cod = B.MON_COD_TP_PROCESSO
    AND A.FLH_FLAG_ANN = 'N'
    AND A.flh_id_messaggio IS NULL
WHERE  B.mon_flag_ann = 'N'

外部結合条件にA.flh_id_messaggio = B.MON_ID_MESSAGGIO A.flh_id_messaggio IS NULLの両方が含まれていますが、両方が true になることはありません。(null の場合でも、 null の比較にB.MON_ID_MESSAGGIOは使用できないため、これは失敗します)。=したがって、外部結合は一致するものを見つけることができず、省略される可能性があるため、MON_MONITORAGGIO_IDからのすべての異なる値をカウントしますB

ただし、IS NULLチェックをWHERE節に移動すると (Gordon が行ったように):

SELECT /*+ PARALLEL (mon, 10) parallel (c 10) */
       COUNT(DISTINCT MON_MONITORAGGIO_ID)
FROM   B
LEFT JOIN A
    ON A.flh_id_messaggio = B.MON_ID_MESSAGGIO
    AND A.flh_tipo_processo_cod = B.MON_COD_TP_PROCESSO
    AND A.FLH_FLAG_ANN = 'N'
WHERE  B.mon_flag_ann = 'N'
    AND A.flh_id_messaggio IS NULL

... then 外部結合条件は一致を見つけることができます。一致が見つからない場合、WHERE句が評価さA.flh_id_messaggioれると実際に になるnullため、これは元の のようになりますNOT EXISTS

また、MON_MONITORAGGIO_ID が一意であるという仮定もありますが、これはおそらくその通りです。しかし、一致がない場合にのみカウントしているので、. は必要ないと思いますDISTINCT

于 2013-01-16T12:39:34.593 に答える