Почему условия CROSS JOIN не работают в предложении ON, только в предложении WHERE?

Мне интересно, почему условное перекрестное соединение должно иметь условия, указанные в предложении WHERE, и почему оно не работает в предложении ON. Смотрите ссылку для скомпилированного примера: http://rextester.com/IKY8693

Бизнес-контекст: мне нужно сгенерировать список дат между начальной и конечной датой, чтобы заполнить пробелы, чтобы оставить соединение с третьей таблицей так, чтобы нули / нули возвращались в течение определенного месяца.

Как я это сделал: возьмем, к примеру, таблицу пользователей с датами начала и окончания ГГГГММ.

| user_id | start_yearmonth | end_yearmonth |
|---------|-----------------|---------------|
| u9876   | 201504          | 201610        |
| u5564   | 201602          | 201612        |
| u4435   | 201606          | NULL          |

Таблица для перекрестного соединения - это таблица желаемых дат ГГГГММ.

| yearmonth |
|-----------|
| 201601    |
| 201602    |
| 201603    |
| 201604    |
| 201605    |
| 201606    |
| 201607    |
| 201608    |
| 201609    |
| 201610    |
| 201611    |
| 201612    |
| 201701    |
| 201702    |

Соединение CROSS с условиями в предложении where работает, но это не работает, когда условия находятся в предложении ON. Это почему?

SELECT
    *
FROM
    user_tbl
    CROSS JOIN date_range
WHERE
    user_tbl.start_yearmonth <= date_range.yearmonth
    AND (user_tbl.end_yearmonth >= date_range.yearmonth
         OR user_tbl.end_yearmonth IS NULL)
ORDER BY 
    user_tbl.user_id, date_range.yearmonth ;

1 ответ

Решение

CROSS JOIN - это оператор SQL для выполнения полного декартового произведения между двумя таблицами. Так как это декартово произведение, оно не допускает каких-либо условий во время операции, вы можете ограничить его результат только с помощью некоторой операции фильтрации (условие WHERE).

Операторы JOIN (INNER и OUTER JOIN, то есть) являются просто декартовым произведением вместе с оператором фильтрации, выраженным в ON-части оператора (и фактически в первоначальном синтаксисе SQL не было оператора JOIN, просто "запятая"). обозначение для обозначения продукта с условием соединения, выраженным всегда в части WHERE).

Примеры:

"старая" запись:

SELECT ...
FROM table1 t1, table2 t2
WHERE t1.attribute = t2.attribute

эквивалентно "современному" обозначению:

SELECT ...
FROM table1 t1 INNER JOIN table2 t2 ON t1.attribute = t2.attribute

в то время как для декартового произведения:

"старая" запись:

SELECT ...
FROM table1 t1, table2 t2

эквивалентно "современному" обозначению:

SELECT ...
FROM table1 t1 CROSS JOIN table2 t2

Другими словами, CROSS JOIN, который требует условия, на самом деле является своего рода INNER JOIN.

Другие вопросы по тегам