Это очень распространенный вопрос, поэтому этот ответ основан на статье, которую я написал.
Таблица отношений
Учитывая , мы имеем следующее 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 JOIN
Предложение SQL JOIN позволяет связывать строки, которые принадлежат разным таблицам. Например, CROSS JOIN создаст декартово произведение, содержащее все возможные комбинации строк между двумя объединяющимися таблицами.
Хотя CROSS JOIN полезен в определенных сценариях, в большинстве случаев вы хотите объединить таблицы на основе определенных условий. И именно здесь INNER JOIN вступает в игру.
SQL INNER JOIN позволяет нам фильтровать декартово произведение объединения двух таблиц на основе условия, указанного в предложении ON.
SQL INNER JOIN - ON «всегда истинное» условие
Если вы укажете условие «всегда верно», INNER JOIN не будет фильтровать объединенные записи, а набор результатов будет содержать декартово произведение двух объединяющихся таблиц.
Например, если мы выполним следующий запрос 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 JOIN - ON «всегда ложное» условие
С другой стороны, если условие предложения 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.review |
| ------ | ------------ | ------- | ----------- | --------- - |
| 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.
Не то чтобы это относится только к ВНУТРЕННЕМУ СОЕДИНЕНИЮ, а не для ВНЕШНЕГО СОЕДИНЕНИЯ