Логика SQL для внутреннего объединения на (A И B) ИЛИ НЕ B - PullRequest
0 голосов
/ 22 октября 2019

Я хочу выполнить внутреннее объединение следующим образом:

SELECT a.Account
FROM TableA a
JOIN TableB b 
  ON (a.Account = b.Account AND a.Source IN (SELECT Source FROM TableC))
  OR a.Source NOT IN (SELECT Source FROM TableC)

Есть ли более простой или эффективный способ сделать это?

Некоторые примеры данных:

Таблица A (учетная запись, источник):

Account | Source
------------------
111     | florida
222     | florida
333     | georgia
444     | alabama
555     | new York

Таблица B (учетная запись):

Account
-------
111
222
333

ТаблицаC (источник):

Source
-------
florida
alabama

Ответы [ 2 ]

0 голосов
/ 22 октября 2019

Мое первое желание состоит в том, чтобы переместить все условия в предложение where:

SELECT a.Account
FROM TableA a
WHERE (EXISTS (SELECT 1 FROM b WHERE a.Account = b.Account) AND
       EXISTS (SELECT 1 FROM TableC c WHERE c.Source = a.Source)
      ) OR
      NOT EXISTS (SELECT 1 FROM TableC c WHERE c.Source = a.Source);

Это дает то преимущество, что вам не нужно беспокоиться о дублирующих результатах, если b имеет несколько строкдля учетной записи.

При наличии соответствующих индексов (для b(Account) и c(Source)) это должно иметь очень хорошую производительность.

Единственное исключение, при котором JOIN будет полезным, - это когдаb очень мало по отношению к a.

0 голосов
/ 22 октября 2019

Я думаю, что запрос может быть переписан с использованием двух левых объединений и предложения WHERE, чтобы избежать повторения условия a.Source [NOT] IN (SELECT Source FROM TableC):

SELECT a.Account
FROM TableA a
LEFT JOIN TableB b ON a.Account = b.Account
LEFT JOIN TableC c ON c.Source = a.Source
WHERE 
    (c.Source IS NOT NULL AND b.Account IS NOT NULL)
    OR c.Source IS NULL

Это означает, что запись в TableAвыбирается либо при успешном соединении, либо если при TableC соединение не выполнено.

...