Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Клауза WHERE срещу ON при използване на JOIN

Просто внимавайте за разликата с външните съединения. Заявка, където филтър на b.IsApproved (в дясната таблица, Bar) се добавя към ON условие на JOIN :

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId); 

Е НЕ същото като поставянето на филтъра в WHERE клауза:

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1); 

Тъй като за 'неуспешни' външни присъединявания към Bar (т.е. където няма b.BarId за f.BarId ), това ще остави b.IsApproved като NULL за всички такива неуспешни редове за присъединяване и тези редове след това ще бъдат филтрирани.

Друг начин да разгледаме това е, че за първата заявка LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId) винаги ще връща ЛЯВИТЕ редове на таблицата, тъй като LEFT OUTER JOIN гарантира, че ЛЯВИТЕ редове на таблицата ще бъдат върнати, дори ако присъединяването е неуспешно. Въпреки това, ефектът от добавянето на (b.IsApproved = 1) към LEFT OUTER JOIN условието е да се нулират всички десни колони на таблицата, когато (b.IsApproved = 1) е невярно, т.е. съгласно същите правила, които обикновено се прилагат към LEFT JOIN условие на (b.BarId = f.BarId) .

Актуализиране :За да завършите въпроса, зададен от Конрад, еквивалентният LOJ за НЕЗАПЪЛНИТЕЛЕН филтър би бил:

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);

т.е. WHERE клаузата трябва да вземе предвид и двете условия дали присъединяването е неуспешно (NULL) и филтърът трябва да се игнорира, а когато свързването е успешно и филтърът трябва да се приложи. (b.IsApproved или b.BarId може да бъде тестван за NULL )

Тук съставих SqlFiddle, който демонстрира разликите между различните разположения на b.IsApproved филтър спрямо JOIN .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как можете да представите наследството в база данни?

  2. Вмъкване на няколко реда в една SQL заявка?

  3. DATEDIFF() срещу DATEDIFF_BIG() в SQL Server:Каква е разликата?

  4. Връзката със SQL Server работи понякога

  5. Грешка 113 на SQL Server:Липсващ знак за краен коментар „*/“