Равенство "выберите ... где в" и объединяет - PullRequest
2 голосов
/ 24 августа 2011

Предположим, у меня есть table1, как это:

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

А table2 вот так:

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

Будут ли следующие два запроса возвращать один и тот же набор результатов при каждом условии?

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

Если бы я действительно не упустил что-то глупое, я бы сказал, да. Но я сделал два запроса, которые сводятся к этой форме, и я получаю разные результаты. Есть несколько вложенных запросов, использующих WHERE IN, но на последнем этапе я заметил, что JOIN намного быстрее. Все вложенные запросы полностью изолированы, поэтому я не верю, что они являются проблемой, поэтому я просто хочу исключить вероятность того, что у меня возникло неправильное представление о вышеизложенном.

Спасибо за любые идеи.

РЕДАКТИРОВАТЬ

Два оригинальных запроса:

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

Хотя я до сих пор не понимаю, почему запросы дали разные результаты, может показаться, что наша логика была ошибочной с самого начала, поскольку в некоторых частях мы использовали неправильные столбцы. Имейте в виду, что я не говорю, что сделал ошибку, интерпретировав запросы, как написано выше, или имел опечатку, нам просто нужно было выбрать что-то другое.

Обычно я не отдыхаю до тех пор, пока не докопаюсь до сути подобных вещей, но я очень устал и вхожу в свой первый отпуск с января, который длится более одного дня, поэтому я не могу беспокоиться о поиске дальше прямо сейчас. Я уверен, что приведенные здесь советы пригодятся позже. За всю помощь были распределены голоса, и я принял ответ Иперкуба, главным образом потому, что его комментарии привели меня к дальнейшему. Но спасибо всем вокруг! Если я узнаю об этом позже, я попытаюсь вспомнить, как пингнулся обратно.

Ответы [ 5 ]

4 голосов
/ 24 августа 2011

Поскольку 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]) )
1 голос
/ 25 августа 2011

Я бы искал там преобразование типов данных.

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;
1 голос
/ 24 августа 2011

Вы также можете попытаться выполнить прямое соединение со второй таблицей

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

Вам не нужно различаться , если элемент является первичным ключом или уникальным

Существует и Внутреннее соединение должно иметь одинаковую скорость выполнения, тогда как IN дороже.

1 голос
/ 24 августа 2011

Оба запроса выполняют полусоединение , то есть никакие атрибуты из table2 не отображаются в самом верхнем SELECT (набор результатов).

На мой взгляд, ваш первый запрос легче всего идентифицировать как полусоединение, EXISTS тем более.С другой стороны, оптимизатор, несомненно, видел бы это иначе;)

1 голос
/ 24 августа 2011

В идеале я хотел бы увидеть различия между наборами результатов.
- Получаете ли вы дублирование записей
- Всегда ли один набор является подмножеством другого
- Есть ли в одном наборе оба«дополнительные» и «пропущенные» записи по сравнению с другими?

Тем не менее, логика должна быть эквивалентной.Моим лучшим предположением было бы то, что у вас там есть пустые строковые записи;потому что версия Oracle NULL CHAR / VARCHAR - просто пустая строка.Это может дать очень интересные результаты, если вы не готовы к этому.

...