2

table1次のようなものがあるとします。

id | itemcode
-------------
1  | c1
2  | c2
...

そして、table2このような:

item | name
-----------
c1   | acme
c2   | foo
...

次の 2 つのクエリは、すべての条件下で同じ結果セットを返しますか?

SELECT id, itemcode 
FROM table1 
WHERE itemcode IN (SELECT DISTINCT item 
                  FROM table2 
                  WHERE name [some arbitrary test])

SELECT id, itemcode 
FROM table1 
   JOIN (SELECT DISTINCT item 
          FROM table2
          WHERE name [some arbitrary test]) items 
         ON table1.itemcode = items.item

ばかげたことを本当に見逃していない限り、私はそう言うでしょう。しかし、この形式に要約される 2 つのクエリを実行したところ、異なる結果が得られました。WHERE IN を使用したネストされたクエリがいくつかありますが、最後のステップでは、JOIN の方がはるかに高速であることに気付きました。ネストされたクエリはすべて完全に分離されているため、問題があるとは思わないので、上記に関して誤解している可能性を排除したいだけです。

洞察をありがとう。

編集

2 つの元のクエリ:

SELECT imitm, imlitm, imglpt 
    FROM jdedata.F4101 
    WHERE imitm IN 
  (SELECT DISTINCT ivitm AS itemno 
       FROM jdedata.F4104 
       WHERE ivcitm IN 
    (SELECT DISTINCT ivcitm AS legacycode 
             FROM jdedata.F4104 
              WHERE ivitm IN 
      (SELECT DISTINCT tritm 
               FROM trigdata.F4101_TRIG)
    )
  )


SELECT orig.imitm, orig.imlitm, orig.imglpt 
    FROM jdedata.F4101 orig 
        JOIN 
        (SELECT DISTINCT ivitm AS itemno 
        FROM jdedata.F4104 
        WHERE ivcitm IN 
              (SELECT DISTINCT ivcitm AS legacycode 
              FROM jdedata.F4104
               WHERE ivitm IN 
                 (SELECT DISTINCT tritm 
                  FROM trigdata.F4101_TRIG))) itemns 
ON orig.imitm = itemns.itemno

編集2

クエリが異なる結果を返した理由はまだわかりませんが、いくつかの部分で間違った列を使用していたため、最初からロジックに欠陥があったようです。上記のようにクエリの解釈を間違えた、またはタイプミスがあったと言っているわけではありません。別のものを選択する必要があっただけです。

普段はこういうことを理解するまで休まないのですが、とても疲れていて、1月以来初めての連休に突入するので、今さら検索する気にはなれません。 . ここで紹介したヒントは、後で役に立つと確信しています。すべてのヘルプに対して賛成票が配布され、Ypercube の回答を受け入れました。これは主に、彼のコメントが私を最も遠ざけたからです。でも、ずっとありがとう!後で詳細が判明した場合は、再度 ping を実行したことを思い出そうとします。

4

5 に答える 5

4

table2.itemは nullable ではないため、2 つのバージョンは同等です。distinctバージョンからを削除できますが、IN必要ありません。これらの 3 つのバージョンとその実行計画を確認できます。

SELECT id, itemcode FROM table1 WHERE itemcode IN
  ( SELECT item FROM table2 WHERE name [some arbitrary test] )

SELECT id, itemcode FROM table1 JOIN
  ( SELECT DISTINCT item FROM table2 WHERE name [some arbitrary test] )
  items ON table1.itemcode = items.item

SELECT id, itemcode FROM table1 WHERE EXISTS
  ( SELECT * FROM table2 WHERE table1.itemcode = table2.item 
                           AND (name [some arbitrary test]) )
于 2011-08-24T12:14:58.560 に答える
1

そこでデータ型変換を探します。

create table t_vc (val varchar2(6));
create table t_c (val char(6));

insert into t_vc values ('12345');
insert into t_vc values ('12345 ');

insert into t_c values ('12345');
insert into t_c values ('12345');

select t_c.val||':'
from t_c
where val in (select distinct val from t_vc);

select c.val||':'
from t_vc v join (select distinct val from t_c) c on v.val=c.val;
于 2011-08-25T05:00:33.213 に答える
1

2 番目のテーブルへの直接結合を試みることもできます

SELECT DISTINCT id, itemcode 
FROM table1 
INNER JOIN table2 ON table1.itemcode = table2.item   
WHERE name [some arbitrary test] )

アイテムが主キーまたは一意の場合、明確にする必要はありません

ExistsInner Joinの実行速度は同じである必要がありますが、 INはより高価です。

于 2011-08-24T13:27:15.473 に答える
1

理想的には、結果セット間の違いを確認したいと思います。
- レコードの重複が発生していますか?
- 1 つのセットは常に他のセットのサブセット
ですか? - 1 つのセットには、他のセットと比較して「追加」レコードと「欠落」レコードの両方がありますか?

つまり、ロジックは同等でなければなりません。私の最善の推測は、そこにいくつかの空の文字列エントリがあることです。Oracle のバージョンの NULL CHAR/VARCHAR は単なる空の文字列であるためです。準備ができていない場合、これは非常にファンキーな結果をもたらす可能性があります。

于 2011-08-24T13:14:04.537 に答える
1

どちらのクエリもセミジョインを実行します。つまり、最上位(結果セット)には属性がtable2表示されません。SELECT

私の目には、最初のクエリはセミジョインとして識別するのが最も簡単で、EXISTSさらにそうです。一方、オプティマイザーは間違いなく別の見方をするでしょう;)

于 2011-08-24T13:16:06.660 に答える