Postgresql 为什么交叉连接条件在“ON”子句中不起作用,而只在WHERE子句中起作用?

Postgresql 为什么交叉连接条件在“ON”子句中不起作用,而只在WHERE子句中起作用?,postgresql,cross-join,Postgresql,Cross Join,我想知道为什么条件交叉连接必须在WHERE子句中指定条件,为什么它在“ON”子句中不起作用。有关编译示例,请参见链接: 业务上下文:我需要生成一个开始日期和结束日期之间的日期列表,以填补空白,以便与第三个表左键联接,从而为特定月份返回零/空 我是如何做到这一点的:让我们以一个用户表为例,其中包含YYYYMM开始和结束日期 | user_id | start_yearmonth | end_yearmonth | |---------|-----------------|-------------

我想知道为什么条件交叉连接必须在WHERE子句中指定条件,为什么它在“ON”子句中不起作用。有关编译示例,请参见链接:

业务上下文:我需要生成一个开始日期和结束日期之间的日期列表,以填补空白,以便与第三个表左键联接,从而为特定月份返回零/空

我是如何做到这一点的:让我们以一个用户表为例,其中包含YYYYMM开始和结束日期

| user_id | start_yearmonth | end_yearmonth |
|---------|-----------------|---------------|
| u9876   | 201504          | 201610        |
| u5564   | 201602          | 201612        |
| u4435   | 201606          | NULL          |
要交叉联接的表是包含所需YYYYMM日期的表

| yearmonth |
|-----------|
| 201601    |
| 201602    |
| 201603    |
| 201604    |
| 201605    |
| 201606    |
| 201607    |
| 201608    |
| 201609    |
| 201610    |
| 201611    |
| 201612    |
| 201701    |
| 201702    |
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 ;

交叉联接是在两个表之间执行完全笛卡尔乘积的SQL运算符。由于它是笛卡尔积,因此在操作过程中不允许任何条件,您只能通过一些过滤操作限制其结果,其中包含条件

联接内部联接和外部联接,即运算符,只是笛卡尔积和在运算符的ON部分表示的过滤运算符,事实上在SQL的原始语法中没有联接运算符,只是用“逗号”符号表示联接条件始终在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
相当于现代符号:

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
而对于笛卡尔积:

旧符号:

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
相当于现代符号:

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

换句话说,需要条件的交叉连接实际上是某种内部连接。

什么意思?交叉联接不支持打开。你可以把它看作是两个集合的笛卡尔积,on没有意义。我想我的问题很清楚——我特别想问为什么交叉连接不支持on“ON”用于在两个表之间创建条件,不是吗?是的,并且不使用交叉联接创建任何条件。其他类型的联接必须满足条件。就这么简单。如果您希望在交叉联接上添加条件,那么您必须在交叉联接语句之外添加条件。这不是交叉联接。它是一个笛卡尔积与一组日期范围记录(与用户记录匹配)的内部联接。说交叉联接的唯一原因是,如果您想要所有行的完全笛卡尔积,那么您不必指定ON子句。就我个人而言,我想说交叉左连接,但那是另一个故事。我仍然不知道为什么有人对这个问题投了反对票。非常好的回答,没有任何空气,谢谢!在标准SQL中,必须使用带内部联接的ON。