SQL Server 2008中的CROSS JOIN与INNER JOIN

时间:2013-07-20 07:05:55

标签: sql sql-server sql-server-2008 tsql cross-join

CROSS JOININNER JOIN之间的区别是什么?

CROSS JOIN:

SELECT 
    Movies.CustomerID, Movies.Movie, Customers.Age, 
    Customers.Gender, Customers.[Education Level], 
    Customers.[Internet Connection], Customers.[Marital Status], 
FROM   
    Customers 
CROSS JOIN 
    Movies

INNER JOIN:

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

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

12 个答案:

答案 0 :(得分:166)

以下是Cross Join和Inner Join的最佳示例。

考虑以下表格

表:Teacher

x------------------------x
| TchrId   | TeacherName | 
x----------|-------------x
|    T1    |    Mary     |
|    T2    |    Jim      |
x------------------------x

表:Student

x--------------------------------------x
|  StudId  |    TchrId   | StudentName | 
x----------|-------------|-------------x            
|    S1    |     T1      |    Vineeth  |
|    S2    |     T1      |    Unni     |
x--------------------------------------x

1。 INNER JOIN

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

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

enter image description here

<强>查询

SELECT T.TchrId,T.TeacherName,S.StudentName 
FROM #Teacher T
INNER JOIN #Student S ON T.TchrId = S.TchrId

<强>结果

x--------------------------------------x
|  TchrId  | TeacherName | StudentName | 
x----------|-------------|-------------x            
|    T1    |     Mary    |    Vineeth  |
|    T1    |     Mary    |    Unni     |
x--------------------------------------x

2。交叉加入

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

考虑我们需要找到学校的所有教师和学生而不论班主任,我们需要申请CROSS JOIN

enter image description here

<强>查询

SELECT T.TchrId,T.TeacherName,S.StudentName 
FROM #Teacher T
CROSS JOIN #Student S 

<强>结果

x--------------------------------------x
|  TchrId  | TeacherName | StudentName | 
x----------|-------------|-------------x            
|    T2    |     Jim     |    Vineeth  |
|    T2    |     Jim     |    Unni     |
|    T1    |     Mary    |    Vineeth  |
|    T1    |     Mary    |    Unni     |
x--------------------------------------x

答案 1 :(得分:105)

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

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

交叉加入

select * from table1 cross join table2 where table1.id = table2.fk_id

内部联接

select * from table1 join table2 on table1.id = table2.fk_id

使用最后一种方法

答案 2 :(得分:62)

CROSS JOIN =(INNER)JOIN =逗号(&#34;,&#34;)

TL; DR SQL CROSS JOIN,(INNER)JOIN和逗号(&#34;,&#34;)之间的唯一区别(除了对评估顺序具有较低优先级的逗号)是(INNER)JOIN有一个ON而CROSS JOIN和逗号没有。


重新介绍中间产品

这三个产生了一个中间概念的SQL风格的关系&#34;笛卡尔&#34;产品,又称交叉连接,来自每个表的行的所有可能组合。它是ON和/或WHERE,减少行数。 SQL Fiddle

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

正如维基百科所说:

  

Cross join

     

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

  

Inner join

     

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

  

&#34;隐式连接符号&#34;只需在SELECT语句的FROM子句中列出要加入的表,使用逗号分隔它们。因此,它指定了交叉连接

重新 OUTER 加入并使用其中的ON与WHERE,请参阅Conditions in LEFT JOIN (OUTER JOIN) vs INNER JOIN

为什么要比较表之间的列?

当没有重复的行时:

每个表都包含从某个fill-in-[ - ]空白语句模板中生成真实语句的行。 (它使 - 中的命题符合 - 某个(特征)谓词。)

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

    /* rows where
    customer C.CustomerID has age C.Age and ...
    */
    FROM Customers C
    
  • 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
    
  • ON&amp;在哪里条件与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)相等的列意味着从连接表中保留产品的行&#39;模板的某些部分对这些列具有相同的(非NULL)值。巧合的是,通常通过表之间的相等比较来删除大量行 - 必要且足够的是表征所需的行。

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

重新查询(和表格与条件)的含义见:
How to get matching data from another SQL table for two different columns: Inner Join and/or Union?
Is there any rule of thumb to construct SQL query from a human-readable description?

重载&#34;交叉加入&#34;

不幸的是,术语&#34;交叉连接&#34;习惯于:

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

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

使用CROSS JOIN vs(INNER)JOIN vs逗号

共同的惯例是:

  • 当且仅当您不比较表之间的列时,才使用CROSS JOIN。这表明缺乏比较是故意的。
  • 当且仅当比较表之间的列时,将(INNER)JOIN与ON一起使用。 (可能还有其他条件。)
  • 不要使用逗号。

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

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

Re Venn图具有两个相交圆的维恩图可以说明INNER,LEFT,RIGHT&amp;的输出行之间的差异。完全连接相同的输入。当ON无条件为TRUE时,INNER JOIN结果与CROSS JOIN相同。它还可以说明INTERSECT,UNION&amp;的输入和输出行。除了。当两个输入具有相同的列时,INTERSECT结果与标准SQL NATURAL JOIN相同,并且EXCEPT结果与涉及LEFT&amp;的某些习语相同。正确的加入。但它说明(INNER)JOIN一般如何工作。只是乍一看似乎是合理的。它可以识别ON,PK(主键),FK(外键)和/或SELECT的特殊情况的输入和/或输出的部分。您需要做的就是确定圈子所代表的集合的元素究竟是什么。 (哪些混乱的演示文稿从未说清楚。)(请记住,通常对于连接输出行与输入行具有不同的标题。而SQL表是 bags 而不是 sets < / em> of rows with NULLs 。)

答案 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

交叉加入

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

交叉连接的语法

SELECT * FROM table_name1
CROSS JOIN table_name2

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

SELECT * FROM table_name1,table_name2

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

实施例

SELECT * FROM UserDetails
CROSS JOIN OrderDetails

或者

SELECT * FROM UserDetails, OrderDetails

答案 4 :(得分:10)

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

答案 5 :(得分:6)

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

使用这种更简单的表示法,无需担心内部和交叉连接之间的区别。而不是两个&#34; ON&#34;条款,有一个&#34; WHERE&#34;完成这项工作的条款。如果您在确定哪些&#34;加入&#34; &#34; ON&#34;条款去哪里,放弃&#34;加入&#34;符号并使用上面更简单的符号。

这不是作弊。

答案 6 :(得分:2)

在使用内部联接编写查询时,如果两个表上的条件都满足,则记录将从两个表中获取,即两个表中公共列的完全匹配。

使用交叉连接编写查询时,结果类似于两个表中记录数的笛卡尔积。例如,如果table1包含2条记录,table2包含3条记录,则查询结果为2 * 3 = 6条记录。

所以在你需要之前不要进行交叉连接。

答案 7 :(得分:2)

交叉连接和内连接是唯一的区别,在内连接中我们布尔过滤笛卡尔积的一些结果

table1
x--------------------------------------x
|  fieldA  |    fieldB   |    fieldC   | 
x----------|-------------|-------------x            
|    A     |      B      |    option1  |
|    A     |      B1     |    option2  |
x--------------------------------------x

table2
x--------------------------------------x
|  fieldA  |    fieldB   |    fieldC   | 
x----------|-------------|-------------x            
|    A     |      B      |    optionB1 |
|    A1    |      B1     |    optionB2 |
x--------------------------------------x

 cross join
  A,B,option1,A,B,optionB1
  A,B,option1,A1,B1,optionB2
  A,B1,option2,A,B,optionB1
  A,B1,option2,A1,B1,optionB2

 inner join on field1 (only with the value is the same in both tables)
  A,B,option1,A,B,optionB1
  A,B1,option2,A,B,optionB1

 inner join on field1
  A,B,option1,A,B,optionB1

在我们的数据设计中,我们决定只有一个我们用于连接的字段的情况。只加入交叉连接两个表,只获得完成特殊布尔表达式的行。

请注意,如果我们正在进行联接的字段在两个表中都为空,我们将通过过滤器。由我们或数据库制造商来添加额外的规则以避免或允许空值。坚持基础,它只是一个交叉连接,后面是一个过滤器。

答案 8 :(得分:2)

交叉加入

正如我在this article中所述,CROSS JOIN用于生成笛卡尔积。

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

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

The ranks and suits tables

ranks包含以下行:

| name  | symbol | rank_value |
|-------|--------|------------|
| Ace   | A      | 14         |
| King  | K      | 13         |
| Queen | Q      | 12         |
| Jack  | J      | 11         |
| Ten   | 10     | 10         |
| Nine  | 9      |  9         |

suits表包含以下记录:

| name    | symbol |
|---------|--------|
| Club    | ♣      |
| Diamond | ♦      |
| Heart   | ♥      |
| Spade   | ♠      |

与CROSS JOIN查询类似,如下所示:

SELECT
   r.symbol AS card_rank,
   s.symbol AS card_suit
FROM
   ranks r
CROSS JOIN
   suits s

将生成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         | ♠         |

内部加入

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

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

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

例如,假设在父表post和子表post_comment之间有一个one-to-many table relationship,如下所示:

One-to-many table relationship

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

| id | title     |
|----|-----------|
| 1  | Java      |
| 2  | Hibernate |
| 3  | JPA       |

post_comments表具有以下行:

| id | review    | post_id |
|----|-----------|---------|
| 1  | Good      | 1       |
| 2  | Excellent | 1       |
| 3  | Awesome   | 2       |

内部联接查询,如下所示:

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

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

| post_id | post_title | review    |
|---------|------------|-----------|
| 1       | Java       | Good      |
| 1       | Java       | Excellent |
| 2       | Hibernate  | Awesome   |
  

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

答案 9 :(得分:0)

内连接将给出两个表之间匹配记录的结果,其中交叉连接为您提供两个表之间可能的组合。

答案 10 :(得分:0)

A = {1,5,3,4,6,7,9,8} B = {2,8,5,4,3,6,9}

cross join充当笛卡尔乘积A✖B = {1,2},{1,8} ...,{5,2},{5,8},{5,5}。 ... {3,3} ...,{6,6} .... {8,9},并返回此长结果集。.

在处理inner join时通过笛卡尔乘积完成并选择匹配对时。如果认为此有序对为 两个表的主键和on子句搜索A = B,然后inner join选择{5,5},{4,4},{6,6},{9,9} 并在与这些ID相关的select子句中返回询问的列。

如果a = b上的cross join,则其结果集与inner join相同。在这种情况下,也请使用inner join

答案 11 :(得分:-1)

这取决于您期望的输出。

交叉联接将一个表中的所有行与另一表中的所有行匹配。内部联接在一个或多个字段上匹配。如果您的一张表有10行,而另一张表有10行,则这两个联接的行为将有所不同。

交叉连接将返回100行,并且它们将不相关,只是所谓的笛卡尔乘积。内部联接将彼此匹配记录。假设其中一个具有主键,而另一个具有外键,则将返回10行。

交叉连接的通用实用程序有限,但是为了完整性起见,它存在并且描述了不添加任何关系到查询的连接表的结果。您可以使用交叉联接来列出单词或类似内容的组合。另一方面,内部联接是最常见的联接。