ИЛИ Условие в Oracle SQL - PullRequest
       41

ИЛИ Условие в Oracle SQL

0 голосов
/ 08 октября 2018

Мы унаследовали набор таблиц от стороннего продукта.Одна из таблиц имеет 2 ограничения внешнего ключа, которые ссылаются на один и тот же столбец в родительской таблице.Я упростил таблицы, чтобы продемонстрировать это:

CREATE TABLE profile_defn 
(   
  profile_id NUMBER(10,0), 
  profile_name  VARCHAR2(50),
  CONSTRAINT pk1 PRIMARY KEY (profile_id)
);

CREATE TABLE letter_defn 
(
  letter_defn_id  NUMBER(10,0), 
  letter_name     VARCHAR2(50 BYTE), 
  orig_print_id   NUMBER(10,0),
  new_print_id    NUMBER(10,0),
  CONSTRAINT fk1 FOREIGN KEY (orig_print_id) REFERENCES profile_defn (profile_id) ENABLE,
  CONSTRAINT fk2 FOREIGN KEY (new_print_id) REFERENCES profile_defn (profile_id) ENABLE
);

INSERT INTO profile_defn
VALUES
(
  1,
  'profile1'
);

INSERT INTO profile_defn
VALUES
(
  2,
  'profile2'
);

INSERT INTO profile_defn
VALUES
(
  3,
  'profile3'
);

INSERT INTO letter_defn
VALUES 
(
  1,
  'letter1',
  1,
  2
);

INSERT INTO letter_defn
VALUES 
(
  1,
  'letter2',
  2,
  3
);

Следовательно, при объединении двух таблиц возникает условие ИЛИ, поскольку необходимо идентифицировать совпадающие записи в любом столбце:

SELECT * FROM letter_defn ld
JOIN profile_defn p 
ON ld.orig_print_id = p.profile_id OR ld.new_print_id = p.profile_id;

ЕстьЕсть ли какие-либо последствия использования OR в JOIN или есть «лучший» способ сделать это?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 08 октября 2018

Наилучшим подходом обычно являются два left join s:

SELECT ld.*, . . .
FROM letter_defn ld LEFT JOIN
     profile_defn po
     ON ld.orig_print_id = po.profile_id LEFT JOIN
     profile_defn pn
     ON ld.new_print_id = p.profile_id 
WHERE po.profile_id IS NOT NULL OR pn.profile_id IS NOT NULL;

. Таким образом столбцы из двух профилей помещаются в одну строку.Запрос может в полной мере использовать индексы.Вы не указываете, как вы хотите, чтобы результаты выглядели.Если вам нужно только одно значение из двух объединений, используйте COALESCE().

0 голосов
/ 08 октября 2018

На всякий случай, если вы решите использовать предложенную альтернативу UNION ALL, учтите тот факт, что любые записи с orig_print_id = new_print_id будут появляться дважды в результатах.

0 голосов
/ 08 октября 2018

Альтернативой будет использование UNION или UNION ALL, который может иметь лучший план выполнения:

SELECT * FROM letter_defn ld 
JOIN profile_defn p ON ld.orig_print_id = p.profile_id 
UNION
SELECT * FROM letter_defn ld 
JOIN profile_defn p ON ld.new_print_id = p.profile_id;

consequences состоит в том, что or обычно медленнее, поскольку компилятор больше не можетвыполнить поиск индекса.Кроме того, все в порядке.

...