从 SQL 到 LINQ, 第6部分: 联接 (Bill Horst)

Categories: Data, LINQ
Comments: 3 Comments
Published on: 2008 年 01 月 28 日

[原文作者]Bill Horst

[原文链接]Converting SQL to LINQ, Part 6: Joins (Bill Horst)

 

本文假设您已阅读了本系列中此前发表的文章:

          SQL LINQ, Part 1: 基础(Bill Horst)

          SQL LINQ, Part 2: FROM SELECT(Bill Horst)

          Converting SQL to LINQ, Part 3: DISTINCT, WHERE, ORDER BY and Operators

          Converting SQL to LINQ, Part 4: Functions

          Converting SQL to LINQ, Part 5: GROUP BY and HAVING

 

本文将讨论一下交叉联接Cross Join, 内联接Inner Join, 自然联接Natural Join 和外(/)联接 Outer (Left/Right) Join.

 

联接

 

在一个SQL SELECT语句中查询一个以上的数据集(例如:)是比较常见的. 把多个表中的信息集中在一起就叫做联接, 而在SQLLINQ中有好几种不同的联接.

 

交叉联接

 

最简单的连接是交叉联接, 又叫笛卡尔积, 是针对两个数据集合的多对多的联接, 一个数据集中的每一条记录与另一个数据集中的每条记录都进行连接. 在一个SQL SELECT语句中, 要实现交叉联接只要在FROM子句中指定一个以上的表就可以了. VB LINQ, 可以用相同的方式实现, 如下所示:

 

SQL

SELECT CustomerTable.Name, OrderTable.OrderDate

FROM CustomerTable, OrderTable

 

 

VB

From Contact In CustomerTable, Shipment In OrderTable _

Select Contact.Name, Shipment.OrderDate

 

 

内联接

 

内联接是一对一的联接, 一个数据集中的记录根据两个数据集中特定的相同字段与另一个数据集中的记录做匹配. 在一个SQL SELECT语句中, 第二个数据集在INNER JOIN子句中指定, 匹配条件在ON子句中指定. 与此类似, VB LINQ联接中, 第二个数据集在Join中指定, On子句则用来指定Equals运算符与哪个字段相匹配.

 

SQL

SELECT Contact.Name, Shipment.OrderID

FROM CustomerTable Contact

INNER JOIN OrderTable Shipment

ON Contact.CustomerID = Shipment.CustomerID

AND Contact.Zip = Shipment.ShippingZip

 

 

VB

From Contact In CustomerTable

Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _

And Contact.Zip Equals Shipment.ShippingZip _

Select Contact.Name, Shipment.OrderID

 

 

上面的例子是一个对等联接, 意味着用一个相等运算符联接两个表的信息. 这是On子句中唯一允许使用的运算符, 所以要想实现其他的联接运算符(例如:小于), 你需要使用一个带Where子句的交叉联接.

 

SQL

SELECT Contact.Name, Shipment.OrderID

FROM CustomerTable Contact

INNER JOIN OrderTable Shipment

ON Contact.CustomerID < Shipment.CustomerID

 

 

VB

From Contact In CustomerTable, Shipment In OrderTable _

Where Contact.CustomerID < Shipment.CustomerID

Select Contact.Name, Shipment.OrderID

 

 

自然联接

 

自然联接也是一对一的联接, 在自然联接中一个数据集中的记录依据两个数据集中所有的相同字段(具有相同的名称)与另一个表中的记录做匹配. 在一个SQL SELECT语句中, 第二个数据集可以在NATURAL JOIN子句中指定, 而用来联接的匹配条件是隐含的. VB LINQ中没有和自然联接直接对应的语法, 所以要实现它的最好方法是创建一个内联接并在On子句中手动指定所有相同字段的相等关系. SQL的自然联接相比, 这显得有点冗长, 但理解起来比较容易.

 

SQL

SELECT * FROM CustomerTable

NATURAL JOIN OrderTable

 

 

VB

From Contact In CustomerTable _

Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _
And Contact.Phone Equals Shipment.Phone

 

 

(/)联接

 

外联接(也被称为左联接或右联接), 是一种一对多的联接, 一个数据集中的每条记录根据两个数据集的相同字段可以与另一个数据集中的多条记录相匹配. 在一个SQL SELECT语句中, 第二个数据集在LEFT JOINRIGHT JOIN子句中指定, 用来联接两个数据集的匹配条件在ON 子句中指定. LEFT JOIN, 第一个()数据集中的每条记录根据匹配条件与第二个表中所有满足匹配条件的记录相联接. 第一个数据集中的所有记录都会出现在结果集中, 不论第二个数据集中有没有与之匹配的记录. 这与RIGHT JOIN相反, 在外联接中所有第二个()数据集中的记录都会出现在结果集中, 并尽可能与第一个数据集中的任何匹配的记录相联接.

 

VB LINQ, 与外连接最相似的结构是分组联接. 在分组联接中, Group Join子句指定了第二个数据集, 并在On子句中提供匹配条件, 这与本文前面描述的联接(内联接)很相像. VB LINQ中还有一个Into子句, 它可以用来指定对每个分组执行什么样的集合运算, 就像是在一个像前面Group Join那样的子句中.

 

SQL LEFT JOIN类似, 分组连接中第一个数据集的每个成员, 与第二个数据集中所有和它相匹配的记录相联接. 再次提醒一下, 如果第二个数据集中没有任何记录与第一个数据集中的某条记录相匹配, 这条记录仍然会出现在结果集中.

 

SQL

SELECT CustomerTable.Name, SUM(OrderTable.Cost) Sum

FROM CustomerTable

LEFT JOIN OrderTable

ON CustomerTable.CustomerID = OrderTable.CustomerID

GROUP BY CustomerTable.Name

 

 

VB

From Contact In CustomerTable _

Group Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _

Into Sum(Shipment.Cost) _

Select Contact.Name, Sum

 

 

实现RIGHT JOIN的最好方式是利用这个Group Join子句, 但需要颠倒其中的表(把后一个表作为第一个).

 

一个比较常见的情况是, 需要使用外联接但不需要进行集合运算. 像上面的示例那样使用Group关键字, 会导致结果被分为一连串大小不等的分组, 下面这个例子可能是VB LINQ中与不需要集合运算的外联接最类似的语法了.

 

SQL

SELECT *

FROM CustomerTable Contact

LEFT JOIN OrderTable Shipment

ON Contact.CustomerID = Shipment.CustomerID

 

 

VB

From Contact In CustomerTable _

Group Join Shipment In OrderTable _

On Contact.CustomerID Equals Shipment.CustomerID _

Into Group

 

 

这些分组联接的例子可能没有涵盖你可能会遇到的LEFT JOIN RIGHT JOIN 的所有情况, 但相信它们会给你一个创建与现有SQL查询相对应的LINQ查询的基本思路.

 

下个星期, 我打算做一个百宝袋”, 主题包括合并(UNION), TOP 和子查询.

 

如果你有任何其他的SQL SELECT语句想要转换到LINQ, 请为本文添加一个关于它回复.

 

-      Bill Horst, VB IDE 测试

3 Comments - Leave a comment
  1. quoted on big truck financeing说道:

    big truck financeing

    从 SQL 到 LINQ, 第6部分: 联接 (Bill Horst) « vbcti

  2. quoted on hobia.co说道:

    hobia.co

    从 SQL 到 LINQ, 第6部分: 联接 (Bill Horst) « vbcti

  3. solidworks说道:

    不错,谢谢楼主分享,学习中……

Leave a comment


Welcome , today is 星期一, 2017 年 03 月 27 日