Фільтрувати таблицю перед застосуванням лівого приєднання


82

У мене є 2 таблиці, я хочу відфільтрувати 1 таблицю до того, як 2 таблиці об’єднаються.

Таблиця клієнтів:

   ╔══════════╦═══════╗
   ║ Customer ║ State ║
   ╠══════════╬═══════╣
   ║ A        ║ S     ║
   ║ B        ║ V     ║
   ║ C        ║ L     ║
   ╚══════════╩═══════╝

Таблиця входу:

   ╔══════════╦═══════╦══════════╗
   ║ Customer ║ Entry ║ Category ║
   ╠══════════╬═══════╬══════════╣
   ║ A        ║  5575 ║ D        ║
   ║ A        ║  6532 ║ C        ║
   ║ A        ║  3215 ║ D        ║
   ║ A        ║  5645 ║ M        ║
   ║ B        ║  3331 ║ A        ║
   ║ B        ║  4445 ║ D        ║
   ╚══════════╩═══════╩══════════╝

Я хочу залишити приєднання, щоб отримати всі записи з таблиці Клієнта, незалежно від того, чи є відповідні записи в таблиці Вступ. Однак я хочу відфільтрувати категорію D у таблиці вступу перед приєднанням .

Бажані результати:

   ╔══════════╦═══════╦═══════╗
   ║ Customer ║ State ║ Entry ║
   ╠══════════╬═══════╬═══════╣
   ║ A        ║ S     ║  5575 ║
   ║ A        ║ S     ║  3215 ║
   ║ B        ║ V     ║  4445 ║
   ║ C        ║ L     ║  NULL ║
   ╚══════════╩═══════╩═══════╝

Якби я мав зробити такий запит:

   SELECT Customer.Customer, Customer.State, Entry.Entry
   FROM Customer
   LEFT JOIN Entry
   ON Customer.Customer=Entry.Customer
   WHERE Entry.Category='D'

Це відфільтрує останній запис.

Тому я хочу, щоб усі рядки з лівої таблиці були приєднані до таблиці входів, відфільтрованої за категорією D.

Завдяки будь-якій допомозі заздалегідь !!


Дивіться це посилання - sqlbenjamin.wordpress.com/2017/12/23/…
MasterJoe

Відповіді:


115

Вам потрібно перенести WHEREфільтр у JOINстан:

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
   AND e.Category='D'

Див. SQL Скрипка з демонстрацією


1
Вау, ви швидкі та ефективні! Це робить трюк, дякую за допомогу!
Том Дженкін

8
@TomJenkin дякую, до речі, ти розмістив на сайті фантастичне перше питання. Багато деталей тощо
Тарин

Дякую - я думаю, що мені сподобається користуватися цим веб-сайтом, сподіваюся, одного дня я зможу зробити такий же внесок, як ви: D
Том Дженкін

2
@bluefeet, але обидва плани виконання рівні, чи не так?
Олексій Жуковський

1
Застосувати фільтрацію до таблиці, від якої залежить приєднання, до приєднання, якщо умови where вказують на першу таблицю. Принаймні на деяких своїх тестах я це бачив. Я розмістив цей коментар у відповідь на коментар Алекса.
Áxel Costas Pena

28

Ви також можете зробити:

SELECT c.Customer, c.State, e.Entry
FROM Customer AS c
LEFT JOIN (SELECT * FROM Entry WHERE Category='D') AS e
ON c.Customer=e.Customer

Скрипка SQL тут


3
@TomJenkin Вибачте за пізню відповідь, я весь цей час був далеко від комп’ютера. Однак з цікавості я пробіг їх обидва і перевірив плани виконання. Плани виконання майже ідентичні, але наскільки це краще, схоже, це версія Bluefeet.
Джефф Розенберг

Чудово, це надихнуло мене виправити свою справу.
sivann

1

Або ...

SELECT c.Customer, c.State, e.Entry
FROM Customer c
LEFT JOIN Entry e
   ON c.Customer=e.Customer
WHERE e.Category IS NULL or e.Category='D'

У SQL умова JOIN виконується перед WHERE. Отже, у запропонованому рішенні об’єднується вся таблиця, а результат фільтрується - що може бути досить дорогим при роботі з великими таблицями. Зазначений стан фільтра повинен бути частиною умови JOIN, як пропонується в інших відповідях
Omley

@Omley Я думаю, ви розгублені щодо того, як працює SQL. SQL є декларативним , а не процедурним . Порядок слів у запиті не робить ніякого впливу на порядок операцій . Це залежить від двигуна. З простого ми бачимо, EXPLAINщо MySql насправді робить незначно кращу оптимізацію цього запиту, ніж той, що вказаний у відповіді Таріна, хоча це, безумовно, буде більше удачі, ніж управління, і зворотне цілком може бути справедливим для іншого движка.
cz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.