CROSS JOIN = (INNER) JOIN = 逗号(",")
简介 SQL中CROSS JOIN、(INNER) JOIN和逗号(",")之间唯一的区别(除了逗号运算符优先级更低)是(INNER) JOIN使用ON子句,而CROSS JOIN和逗号不需要。
关于中间产物
这三种方法都会产生一个中间概念性的SQL样式关系型“笛卡尔”积,即两个表中所有可能的行组合。通过使用ON和/或WHERE来减少行数。SQL Fiddle
SQL标准通过product(7.5 1.b.ii)定义了,通过<comma>定义了<cross join> aka CROSS JOIN(7.7 1.a),通过<comma>加上WHERE以及<search condition>定义了(INNER) JOIN ON(7.7 1.b)。
维基百科解释如下:
Cross join
CROSS JOIN返回连接中各表的行的笛卡尔积。换句话说,它将产生将第一个表中的每一行与第二个表中的每一行组合在一起的行。
Inner join
[...]连接结果可以定义为首先对表中所有记录进行笛卡尔积(或Cross join),然后返回满足连接谓词的所有记录。
“隐式连接表示法”只需在SELECT语句的FROM子句中列出要连接的表,用逗号分隔它们即可。因此,它指定了一个cross join。
一些SQL允许使用无ON的非标准(INNER)JOIN进行cross join。
关于OUTER JOIN请参见我的答案What is the difference between "INNER JOIN" and "OUTER JOIN"?。
关于OUTER JOIN和在其中使用ON vs WHERE,请参见我的答案Conditions in LEFT JOIN (OUTER JOIN) vs INNER JOIN。
为什么要比较表之间的列?
当没有重复行时:
每个表都保存从某个填空-[命名-]模板中得到真命题的行。(它从某个(特征)谓词中得到真命题。)
基表保存了从一些由DBA给出的模板中获得真命题的行:
/* rows where
customer C.CustomerID has age C.Age and ...
*/
FROM Customers C
连接操作的中间产物是包含来自操作数模板AND运算结果为真的行的表格:
/* rows where
customer C.CustomerID has age C.Age and ...
AND movie M.Movie is rented by customer M.CustomerID and ...
*/
FROM Customers C CROSS JOIN Movies M
ON和WHERE条件AND连接,形成更进一步的模板,值仍然是符合该模板的行:
/* rows where
customer C.CustomerID has age C.Age and ...
AND movie M.Movie is rented by customer M.CustomerID and ...
AND C.CustomerID = M.CustomerID
AND C.Age >= M.[Minimum Age]
AND C.Age = 18
*/
FROM Customers C INNER JOIN Movies M
ON C.CustomerID = M.CustomerID
AND C.Age >= M.[Minimum Age]
WHERE C.Age = 18
比较两个表之间(SQL)列的相等性,意味着模板的连接表部分生成的乘积中保留的行具有这些列的相同(非NULL)值。通常通过表之间的等式比较删除了许多行,这只是巧合--必要和充分的是描述您想要的行的模板的SQL。
只需编写所需行的模板SQL代码!
关于查询的含义(表与条件),请参见:
如何获取另一个SQL表的匹配数据,用于两个不同的列:内部联接和/或联合?
是否有任何经验法则可以从可读的描述构造SQL查询?
"交叉联接"的重载
不幸的是,“交叉联接”一词用于以下情况:
- 中间产品。
- CROSS JOIN。
- (INNER) JOIN,其中ON或WHERE未将一个表的任何列与另一个表的任何列进行比较。(因为这可能会返回许多中间产品行)
使用CROSS JOIN vs (INNER) JOIN vs 逗号
常见约定是:
- 仅当您不比较表之间的列时,才使用CROSS JOIN。这是为了显示缺少比较是有意的。
- 只有在比较表之间的列时(可能还有其他条件)时,才使用(INNER) JOIN with ON。
- 不要使用逗号。
通常,不涉及表对的条件保留为WHERE条件。但是,它们可能必须放入(INNER) JOIN ON中,以获取适当的行,以供RIGHT、LEFT或FULL(OUTER) JOIN的参数。
关于“不要使用逗号” 混合使用逗号和明确的JOIN可能会产生误导,因为逗号的优先级较低。但是,考虑到CROSS JOIN、(INNER) JOIN和逗号的意义中间产品的作用,不使用逗号的约定的论据是站不住脚的。CROSS JOIN或逗号就像ON TRUE条件的(INNER) JOIN一样。中间产品、ON和WHERE在相应的谓词中都引入AND。无论如何,内联接ON可以被认为是什么-例如,仅在找到满足ON条件的一对输入行时生成输出行——它仍然返回满足条件的交叉连接行。ON必须补充逗号在SQL中的唯一原因是编写OUTER JOINS。当然,一个表达式应该使其含义清晰;但是,清晰取决于对事物的理解。
关于Venn图,一个有两个相交圆的Venn图可以展示INNER、LEFT、RIGHT和FULL JOIN的输出行在相同输入情况下的差异。当ON无条件为TRUE时,INNER JOIN结果与CROSS JOIN相同。同时,它可以展示INTERSECT、UNION和EXCEPT的输入和输出行。当两个输入具有相同的列时,INTERSECT结果与标准SQL NATURAL JOIN相同,而EXCEPT结果则与一些涉及LEFT和RIGHT JOIN的特定惯用语相同。但它不能总体上说明(INNER) JOIN的工作原理,这只是乍一看似乎是这样。它可以识别ON、PK(主键)、FK(外键)和/或SELECT的特殊情况中的输入和/或输出的部分。你所需要做的就是确定由这些圆所表示的集合的元素是什么。正如混乱的展示从未表明的那样。请记住,在JOIN中,输出行与输入行具有不同的标题。而且SQL表是带有NULL的行的包而不是集合。
请查看我的回答:
Venn Diagram for Natural Join。
CROSS JOIN
将会得到两个表的所有可能组合,例如:有一个拥有100行数据的Table1和另一个拥有100行数据的Table2,那么结果将会是10000条记录。 - bummix CROSS JOIN y
isx INNER JOIN y ON 1=1
- philipxy