SQL Server 2008中的CROSS JOIN与INNER JOIN

Pri*_*ton 133 sql t-sql sql-server cross-join sql-server-2008

CROSS JOIN和之间有什么区别INNER JOIN

交叉加入:

SELECT 
    Movies.CustomerID, Movies.Movie, Customers.Age, 
    Customers.Gender, Customers.[Education Level], 
    Customers.[Internet Connection], Customers.[Marital Status], 
FROM   
    Customers 
CROSS JOIN 
    Movies
Run Code Online (Sandbox Code Playgroud)

内部联接:

SELECT 
    Movies.CustomerID, Movies.Movie, Customers.Age, 
    Customers.Gender, Customers.[Education Level], 
    Customers.[Internet Connection], Customers.[Marital Status]
FROM   
    Customers 
INNER JOIN 
    Movies ON Customers.CustomerID = Movies.CustomerID
Run Code Online (Sandbox Code Playgroud)

哪一个更好,为什么我会使用其中一个?

Sar*_*avu 176

这是交叉连接和内部连接的最佳示例.

请考虑以下表格

表: Teacher

x------------------------x
| TchrId   | TeacherName | 
x----------|-------------x
|    T1    |    Mary     |
|    T2    |    Jim      |
x------------------------x
Run Code Online (Sandbox Code Playgroud)

表: Student

x--------------------------------------x
|  StudId  |    TchrId   | StudentName | 
x----------|-------------|-------------x            
|    S1    |     T1      |    Vineeth  |
|    S2    |     T1      |    Unni     |
x--------------------------------------x
Run Code Online (Sandbox Code Playgroud)

1.内部联系

内部联接选择满足两个表的行.

考虑一下我们需要找到班级老师及其相应学生的老师.在这种情况下,我们需要申请JOININNER JOIN将会

在此输入图像描述

询问

SELECT T.TchrId,T.TeacherName,S.StudentName 
FROM #Teacher T
INNER JOIN #Student S ON T.TchrId = S.TchrId
Run Code Online (Sandbox Code Playgroud)

结果

x--------------------------------------x
|  TchrId  | TeacherName | StudentName | 
x----------|-------------|-------------x            
|    T1    |     Mary    |    Vineeth  |
|    T1    |     Mary    |    Unni     |
x--------------------------------------x
Run Code Online (Sandbox Code Playgroud)

2.交叉加入

交叉连接选择第一个表中的所有行和第二个表中的所有行并显示为笛卡尔积,即具有所有可能性

考虑我们需要找到学校中的所有教师和学生而不管班级教师,我们需要申请CROSS JOIN.

在此输入图像描述

询问

SELECT T.TchrId,T.TeacherName,S.StudentName 
FROM #Teacher T
CROSS JOIN #Student S 
Run Code Online (Sandbox Code Playgroud)

结果

x--------------------------------------x
|  TchrId  | TeacherName | StudentName | 
x----------|-------------|-------------x            
|    T2    |     Jim     |    Vineeth  |
|    T2    |     Jim     |    Unni     |
|    T1    |     Mary    |    Vineeth  |
|    T1    |     Mary    |    Unni     |
x--------------------------------------x
Run Code Online (Sandbox Code Playgroud)

  • 图 2 的关键很复杂:它包围了 CROSS JOIN 参数的(颜色不相关)元素,数字(值不相关)是它的一行,一行(颜色不相关)是结果行。对于作为包的表格,它*不是*维恩图:对于作为值的行,它是*错误的*;对于作为元素的行,它们“不能”共享。对于作为集合的表,您不需要*维恩图。图 1 是解释 JOIN 的常见“糟糕”尝试。它的关键也很复杂:它仅适用于作为集合的表&仅等值连接&仅一个值;它还表示输入与输出不同。一般来说,为 JOIN 写*it*。 (2认同)
  • 感谢您的建议。不管怎样,OP已经询问了这两个连接之间的区别。我以这样的方式回答这个问题,任何初学者都可以轻松理解它们之间的区别。正如您所说,我没有像生产环境中那样提供密钥。只是举个例子,方便理解。对于“Cross Join”,您是否认为除非给出“Where”子句,否则它不会返回所有行?从您的评论来看,初学者更有可能感到困惑!@philipxy (2认同)

t-c*_*.dk 110

交叉连接不会组合行,如果每个表中有100行与1对1匹配,则得到10.000结果,Innerjoin在相同情况下只返回100行.

这两个示例将返回相同的结果:

交叉加入

select * from table1 cross join table2 where table1.id = table2.fk_id
Run Code Online (Sandbox Code Playgroud)

内部联接

select * from table1 join table2 on table1.id = table2.fk_id
Run Code Online (Sandbox Code Playgroud)

使用最后一种方法

  • 我相信你可以写一个`select*from table1 cross join table2 where table1.id = table2.fk_id`作为`select*from table1,table2 where table1.id = table2.fk_id`(用`替换`cross join`) `) (6认同)
  • @Lucas这是连接的旧语法,但它会起作用.我推荐clausen的版本,更具可读性. (5认同)

phi*_*pxy 65

CROSS JOIN =(INNER)JOIN =逗号(",")

TL; DR SQL CROSS JOIN,(INNER)JOIN和逗号(",")之间的唯一区别(除了逗号具有较低的评估顺序优先级)是(INNER)JOIN具有ON而CROSS JOIN和逗号不具有ON.


重新中间产品

这三个产生了每个表中一行的所有可能组合的中间概念SQL样式关系"笛卡尔""交叉"乘积.它是ON和/或WHERE,减少行数.SQL小提琴

SQL标准通过产品(7.5 1.b.ii)定义 <逗号>,<交叉连接>通过<逗号>(7.7 1.a)和JOIN ON <搜索条件>通过<逗号>加WHERE(7.7 1.b)定义).

正如维基百科所说:

交叉加入

CROSS JOIN从连接中的表返回行的笛卡尔积.换句话说,它将产生将第一个表中的每一行与第二个表中的每一行组合在一起的行.

内部联接

[...]连接的结果可以定义为首先获取表中所有记录的笛卡尔积(或交叉连接)的结果(将表A中的每个记录与表B中的每个记录组合)然后返回满足连接谓词的所有记录.

"隐式连接表示法"只是在SELECT语句的FROM子句中列出要加入的表,使用逗号分隔它们.因此,它指定了交叉连接

Re OUTER JOINs&ON vs WHERE in the LE JOIN(OUTER JOIN)vs INNER JOIN中的条件.

为什么比较表之间的列?

每个表都包含从某个fill-in-[ - ]空白语句模板中生成真实语句的行.(它得出了一个真正的命题 - 满足 -某个(特征)谓词.)

  • 基表包含从某个DBA给定的语句模板生成true语句的行:

    /* rows where
    customer C.CustomerID has age C.Age and ...
    */
    FROM Customers C
    
    Run Code Online (Sandbox Code Playgroud)
  • join的中间产品包含从其操作数模板的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
    
    Run Code Online (Sandbox Code Playgroud)
  • 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
    
    Run Code Online (Sandbox Code Playgroud)

特别是,比较列之间的相等性意味着从产品中保留的行与模板的连接表部分具有相同的值.巧合的是,通常通过表之间的相等比较来删除大量行 - 必要且充分的是表征所需的行.

只需为您想要的行的模板编写SQL!

重新查询(以及表与条件)的含义请参阅:
如何从另一个SQL表中获取两个不同列的匹配数据:内部联接和/或联盟?
从人类可读的描述中构造SQL查询是否有任何经验法则?

重载"交叉连接"

不幸的是,术语"交叉连接"用于:

  • 中间产品.
  • 交叉加入.
  • (INNER)JOIN与ON或WHERE不会将一个表中的任何列与另一个表的任何列进行比较.(因为这往往会返回如此多的中间产品行.)

这些不同的含义变得混乱.(例如,在此处的其他答案和评论中.)

使用CROSS JOIN vs(INNER)JOIN vs comma

共同的惯例是:

  • 当且仅当您不比较表之间的列时,才使用CROSS JOIN.这表明缺乏比较是故意的.
  • 当且仅当比较表之间的列时,使用(INNER)JOIN和ON(加上可能的其他条件.)
  • 不要使用逗号.

通常,对于WHERE,也保留不在表对上的条件.但是它们可能必须放在(n INNER)JOIN ON中,以便为RIGHT,LEFT或FULL(OUTER)JOIN的参数获取适当的行.

重新"不要使用逗号"混合逗号与显式JOIN会误导,因为逗号的优先级较低.但鉴于中间产品在CROSS JOIN,(INNER)JOIN和逗号含义中的作用,上述惯例的论据根本不使用它是不稳定的.CROSS JOIN或逗号就像(INNER)JOIN一样,处于TRUE状态.中间产品ON和WHERE都在相应的谓词中引入AND.然而,INNER JOIN ON可以被认为是 - 比如,只有在找到满足ON条件的一对输入行时才生成输出行 - 它仍会返回满足条件的交叉连接行.ON 必须在SQL中补充逗号的唯一原因是写OUTER JOIN.当然,表达应该明确其含义; 但是什么是明确的取决于什么是意味着什么.

Re 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的特殊情况的输入和/或输出部分.要做到这一点,您只需要确定圆圈所代表的集合的元素究竟是什么.(哪些混乱的演示文稿从未说清楚.)(请记住,通常对于连接,输出行输入行具有不同的标题.)

  • +1我最喜欢这个答案 - 其他人似乎暗示结果会有所不同,但如果"ON"子句被"WHERE"替换,结果是相同的 (4认同)
  • 这是正确的答案,与评分较高的答案不同。SQL 的典型情况是,尽管无法理解或定义该语言的基础知识,但表面上、听起来合理、格式良好且带有图片的解释占据了教育内容的主导地位。 (4认同)
  • +1感谢您清除在INNER JOIN中省略ON子句将产生与使用CROSS JOIN完全相同的结果 (3认同)

小智 23

内部联接

仅显示在两个连接表中具有匹配项的行的连接称为内连接.这是查询和视图设计器中的默认连接.

内连接的语法

SELECT t1.column_name,t2.column_name
FROM table_name1 t1
INNER JOIN table_name2 t2
ON t1.column_name=t2.column_name
Run Code Online (Sandbox Code Playgroud)

交叉加入

交叉连接,用于生成参与连接的表的笛卡尔积.笛卡尔积的大小是第一个表中的行数乘以第二个表中的行数.

交叉连接的语法

SELECT * FROM table_name1
CROSS JOIN table_name2
Run Code Online (Sandbox Code Playgroud)

或者我们也可以用另一种方式写它

SELECT * FROM table_name1,table_name2
Run Code Online (Sandbox Code Playgroud)

现在检查以下查询以进行交叉连接

SELECT * FROM UserDetails
CROSS JOIN OrderDetails
Run Code Online (Sandbox Code Playgroud)

要么

SELECT * FROM UserDetails, OrderDetails
Run Code Online (Sandbox Code Playgroud)


Vla*_*cea 13

交叉连接

ACROSS JOIN 旨在生成笛卡尔积。

笛卡尔积采用两组 A 和 B,并从两组给定的数据中生成对记录的所有可能排列。

例如,假设您有以下rankssuits数据库表:

等级和西装表

并且ranks有以下几行:

| name  | symbol | rank_value |
|-------|--------|------------|
| Ace   | A      | 14         |
| King  | K      | 13         |
| Queen | Q      | 12         |
| Jack  | J      | 11         |
| Ten   | 10     | 10         |
| Nine  | 9      |  9         |
Run Code Online (Sandbox Code Playgroud)

虽然该suits表包含以下记录:

| name    | symbol |
|---------|--------|
| Club    | ?      |
| Diamond | ?      |
| Heart   | ?      |
| Spade   | ?      |
Run Code Online (Sandbox Code Playgroud)

作为 CROSS JOIN 查询,如下所示:

SELECT
   r.symbol AS card_rank,
   s.symbol AS card_suit
FROM
   ranks r
CROSS JOIN
   suits s
Run Code Online (Sandbox Code Playgroud)

将生成rankssuites对的所有可能排列:

| card_rank | card_suit |
|-----------|-----------|
| A         | ?         |
| A         | ?         |
| A         | ?         |
| A         | ?         |
| K         | ?         |
| K         | ?         |
| K         | ?         |
| K         | ?         |
| Q         | ?         |
| Q         | ?         |
| Q         | ?         |
| Q         | ?         |
| J         | ?         |
| J         | ?         |
| J         | ?         |
| J         | ?         |
| 10        | ?         |
| 10        | ?         |
| 10        | ?         |
| 10        | ?         |
| 9         | ?         |
| 9         | ?         |
| 9         | ?         |
| 9         | ?         |
Run Code Online (Sandbox Code Playgroud)

内部联接

另一方面,INNER JOIN 不返回两个连接数据集的笛卡尔积。

相反,INNER JOIN 从左侧表中获取所有元素,并将它们与右侧表中的记录进行匹配,以便:

  • 如果右侧表没有匹配到记录,则从结果集中过滤掉左侧行
  • 对于右侧表上的任何匹配记录,左侧行会重复,就好像该记录与其右侧表上所有关联的子记录之间存在笛卡尔积一样。

例如,假设我们在父表post和子post_comment表之间有一个一对多的表关系,如下所示:

一对多表关系

现在,如果该post表有以下记录:

| id | title     |
|----|-----------|
| 1  | Java      |
| 2  | Hibernate |
| 3  | JPA       |
Run Code Online (Sandbox Code Playgroud)

并且该post_comments表有这些行:

| id | review    | post_id |
|----|-----------|---------|
| 1  | Good      | 1       |
| 2  | Excellent | 1       |
| 3  | Awesome   | 2       |
Run Code Online (Sandbox Code Playgroud)

如下所示的 INNER JOIN 查询:

SELECT
   p.id AS post_id,
   p.title AS post_title,
   pc.review  AS review
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
Run Code Online (Sandbox Code Playgroud)

将包括所有post记录及其所有相关联post_comments

| post_id | post_title | review    |
|---------|------------|-----------|
| 1       | Java       | Good      |
| 1       | Java       | Excellent |
| 2       | Hibernate  | Awesome   |
Run Code Online (Sandbox Code Playgroud)

基本上,您可以将其INNER JOIN视为过滤后的 CROSS JOIN,其中只有匹配的记录保留在最终结果集中。


小智 11

请记住,如果添加WHERE子句,则交叉连接表现为内部联接.例如,以下Transact-SQL查询生成相同的结果集.请参阅http://technet.microsoft.com/en-us/library/ms190690(v=sql.105).aspx


小智 7

SQL Server还接受更简单的表示法:

SELECT A.F, 
       B.G, 
       C.H 
  FROM TABLE_A A, 
       TABLE_B B, 
       TABLE_C C
 WHERE A.X = B.X 
   AND B.Y = C.Y
Run Code Online (Sandbox Code Playgroud)

使用这种更简单的表示法,不需要担心内部和交叉连接之间的差异.而不是两个"ON"子句,有一个"WHERE"子句来完成这项工作.如果您在确定哪个"JOIN""ON"子句去哪里时遇到任何困难,请放弃"JOIN"符号并使用上面更简单的符号.

这不是作弊.


归档时间:

查看次数:

351375 次

最近记录:

6 年,11 月 前