Це дуже поширене питання, тому ця відповідь заснована на цій статті, яку я написав.
Табличні відносини
Враховуючи, що ми маємо наступні post
та post_comment
таблиці:
post
Має такі записи:
| id | title |
|----|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
і post_comment
має наступні три ряди:
| id | review | post_id |
|----|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
SQL INNER ПРИЄДНАЙТЕСЬ
Запит SQL JOIN дозволяє асоціювати рядки, що належать до різних таблиць. Наприклад, CROSS JOIN створить декартовий продукт, що містить усі можливі комбінації рядків між двома таблицями з'єднання.
Хоча CROSS JOIN корисний у певних сценаріях, більшу частину часу ви хочете приєднати до таблиць на основі конкретної умови. І ось тут грає INNER JOIN.
SQL INNER JOIN дозволяє нам фільтрувати декартовий продукт об'єднання двох таблиць на основі умови, визначеної за допомогою пункту ON.
SQL INNER ПРИЄДНАЙТЕСЬ - УВІМКНЕНО "завжди істинна" умова
Якщо ви надаєте "завжди справжню" умову, ВНУТРІШНЯ ПРИЄДНАННЯ не буде фільтрувати об'єднані записи, а набір результатів міститиме декартовий продукт двох таблиць приєднання.
Наприклад, якщо ми виконуємо наступний запит SQL INNER JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
Ми отримаємо всі комбінації post
та post_comment
записи:
| p.id | pc.id |
|---------|------------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
Отже, якщо умова пункту ON "завжди відповідає дійсності", INNER JOIN просто еквівалентний запиту CROSS JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SQL INNER ПРИЄДНАЙТЕСЬ - УВІМКНЕНО "завжди помилкова" умова
З іншого боку, якщо умова пропозиції ON "завжди хибна", всі об'єднані записи будуть відфільтровані, а набір результатів буде порожнім.
Отже, якщо ми виконаємо наступний запит SQL INNER JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
Ми не отримаємо жодного результату:
| p.id | pc.id |
|---------|------------|
Це тому, що вищезазначений запит еквівалентний наступному запиту CROSS JOIN:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
Пропозиція SQL INNER JOIN - ON, використовуючи стовпці "Зовнішній ключ" та "Первинний ключ"
Найпоширеніша умова пункту ON - це та, яка відповідає стовпцю «Іноземний ключ» у дочірній таблиці зі стовпцем «Первинний ключ» у батьківській таблиці, як це проілюстровано наступним запитом:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id
Виконуючи вищезазначений запит SQL INNER JOIN, ми отримуємо такий набір результатів:
| p.id | pc.post_id | pc.id | p.title | pc.review |
|---------|------------|------------|------------|-----------|
| 1 | 1 | 1 | Java | Good |
| 1 | 1 | 2 | Java | Excellent |
| 2 | 2 | 3 | Hibernate | Awesome |
Отже, до набору результатів запитів включаються лише записи, які відповідають умові пропозиції ON. У нашому випадку набір результатів містить усі post
разом з їх post_comment
записами. Ці post
рядки , які не пов'язані post_comment
виключені , так як вони не можуть задовольняти умові ON Clause.
Знову вищезазначений запит SQL INNER JOIN еквівалентний наступному запиту CROSS JOIN:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
Рядки без удару - це ті, що відповідають умові WHERE, і лише ці записи будуть включені до набору результатів. Це найкращий спосіб уявити, як працює пункт INNER JOIN.
| p.id | pc.post_id | pc.id | p.title | pc.перегляд |
| ------ | ------------ | ------- | ----------- | --------- - |
| 1 | 1 | 1 | Java | Добре |
| 1 | 1 | 2 | Java | Відмінно |
| 1 | 2 | 3 | Java | Дивовижна |
| 2 | 1 | 1 | Зимує | Добре |
| 2 | 1 | 2 | Зимує | Відмінно |
| 2 | 2 | 3 | Зимує | Дивовижна |
| 3 | 1 | 1 | JPA | Добре |
| 3 | 1 | 2 | JPA | Відмінно |
| 3 | 2 | 3 | JPA | Дивовижна |
Висновок
Оператор INNER JOIN може бути переписаний як CROSS JOIN із пунктом WHERE, який відповідає тому ж умові, який ви використовували в пункті ON запиту INNER JOIN.
Не те, що це стосується лише ВНУТРІШНЬОГО ПРИЄДНАННЯ, а не до зовнішнього приєднання.