LINQ体验(6)——LINQ语句之Join和Order By

简介:

Join操作

 

适用场景:在我们表关系中有一对一关系,一对多关系,多对多关系等。对各个表之间的关系,就用这些实现对多个表的操作。

说明:在Join操作中,分别为Join(Join查询), SelectMany(Select一对多选择)和GroupJoin(分组Join查询)。
该扩展方法对两个序列中键匹配的元素进行inner join操作

SelectMany

 

说明:我们在写查询语句时,如果被翻译成SelectMany需要满足2个条件。1:查询语句中没有join和into,2:必须出现EntitySet。在我们表关系中有一对一关系,一对多关系,多对多关系等,下面分别介绍一下。

1.1 to Many关系:

var q =    from c in db.Customers    from o in c.Orders    where c.City == "London"    select o;

语句描述:Customers与Orders是一对多关系。即Orders在Customers类中以EntitySet形式出现。所以第二个from是从c.Orders而不是db.Orders里进行筛选。

var q =    from p in db.Products    where p.Supplier.Country == "USA" && p.UnitsInStock == 0    select p;

语句描述:这一句使用了p.Supplier.Country条件,间接关联了Supplier表。生成SQL语句为:

SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID],[t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder],[t0].[ReorderLevel], [t0].[Discontinued]FROM [dbo].[Products] AS [t0]LEFT OUTER JOIN [dbo].[Suppliers] AS [t1] ON [t1].[SupplierID] = [t0].[SupplierID]WHERE ([t1].[Country] = @p0) AND ([t0].[UnitsInStock] = @p1)-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [USA]-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0]

2.Many to Many关系:

var q =    from e in db.Employees    from et in e.EmployeeTerritories    where e.City == "Seattle"    select new {e.FirstName, e.LastName, et.Territory.TerritoryDescription};

说明:多对多关系一般会涉及三个表(如果有一个表是自关联的,那有可能只有2个表)。这一句语句涉及Employees, EmployeeTerritories, Territories三个表。它们的关系是1:M:1。Employees和Territories没有很明确的关系。

语句描述:这条生成SQL语句为:
SELECT [t0].[FirstName], [t0].[LastName], [t2].[TerritoryDescription]
FROM [dbo].[Employees] AS [t0]
CROSS JOIN [dbo].[EmployeeTerritories] AS [t1]
INNER JOIN [dbo].[Territories] AS [t2] ON [t2].[TerritoryID] = [t1].[TerritoryID]
WHERE ([t0].[City] = @p0) AND ([t1].[EmployeeID] = [t0].[EmployeeID])
-- @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Seattle]

3.自关联关系:

var q =    from e1 in db.Employees    from e2 in e1.Employees    where e1.City == e2.City    select new {        FirstName1 = e1.FirstName, LastName1 = e1.LastName,        FirstName2 = e2.FirstName, LastName2 = e2.LastName,        e1.City    };

生成SQL语句为:
SELECT [t0].[FirstName] AS [FirstName1], [t0].[LastName] AS [LastName1], [t1].[FirstName] AS [FirstName2], [t1].[LastName] AS [LastName2], [t0].[City]
FROM [dbo].[Employees] AS [t0], [dbo].[Employees] AS [t1]
WHERE ([t0].[City] = [t1].[City]) AND ([t1].[ReportsTo] = [t0].[EmployeeID])

GroupJoin

像上面所说的,没有join和into,被翻译成SelectMany,同时有join和into时,那么就被翻译为GroupJoin。在这里into的概念是对其结果进行重新命名。

1.Two way join(两个表联合查询)

var q =    from c in db.Customers    join o in db.Orders on c.CustomerID equals o.CustomerID into orders    select new {c.ContactName, OrderCount = orders.Count()};

说明:在一对多关系中,左边是1,它每条记录为c(from c in db.Customers),右边是Many,其每条记录叫做o ( join o in db.Orders ),每对应左边的一个c,就会有一组o,那这一组o,就叫做orders,也就是说,我们把一组o命名为orders,这就是into用途。这也就是为什么在select语句中,orders可以调用聚合函数Count。在T-SQL中,使用其内嵌的T-SQL返回值作为字段值。如图所示:

GroupJoin示意图

生成SQL语句为:
SELECT [t0].[ContactName], (
    SELECT COUNT(*)
    FROM [dbo].[Orders] AS [t1]
    WHERE [t0].[CustomerID] = [t1].[CustomerID]
) AS [OrderCount]
FROM [dbo].[Customers] AS [t0]

2.There way join(三个表联合查询)

var q =    from c in db.Customers    join o in db.Orders on c.CustomerID equals o.CustomerID into ords    join e in db.Employees on c.City equals e.City into emps    select new {c.ContactName, ords=ords.Count(), emps=emps.Count()};

生成SQL语句为:
SELECT [t0].[ContactName], (
SELECT COUNT(*)
FROM [dbo].[Orders] AS [t1]
WHERE [t0].[CustomerID] = [t1].[CustomerID]
) AS [ords], (
SELECT COUNT(*)
FROM [dbo].[Employees] AS [t2]
WHERE [t0].[City] = [t2].[City]
) AS [emps]
FROM [dbo].[Customers] AS [t0]

3.Left Outer Join

var q =    from e in db.Employees    join o in db.Orders on e equals o.Employee into ords    from o in ords.DefaultIfEmpty()    select new {e.FirstName, e.LastName, Order = o};

说明:以Employees左表,Orders右表,Orders 表中为空时,用null值填充。Join的结果重命名ords,使用DefaultIfEmpty()函数对其再次查询。其最后的结果中有个Order,因为from o in ords.DefaultIfEmpty() 是对ords组再一次遍历,所以,最后结果中的Order并不是一个集合。但是,如果没有from o in ords.DefaultIfEmpty() 这句,最后的select语句写成select new { e.FirstName, e.LastName, Order = ords }的话,那么Order就是一个集合。

4.Projected let assignment

说明:let语句是重命名。let位于第一个from和select语句之间。

var q =    from c in db.Customers    join o in db.Orders on c.CustomerID equals o.CustomerID into ords    let z = c.City + c.Country    from o in ords    select new {c.ContactName, o.OrderID, z};

5.Composite Key(组合键)

var q =    from o in db.Orders    from p in db.Products    join d in db.OrderDetails        on new {o.OrderID, p.ProductID} equals new {d.OrderID, d.ProductID}        into details    from d in details    select new {o.OrderID, p.ProductID, d.UnitPrice};

说明:使用三个表,并且用匿名类来表示它们之间的关系。它们之间的关系不能用一个键描述清楚,所以用匿名类,来表示组合键。还有一种是两个表之间是用组合键表示关系的,不需要使用匿名类。

6.Nullable/Nonnullable Key Relationship

var q =    from o in db.Orders    join e in db.Employees        on o.EmployeeID equals (int?)e.EmployeeID into emps    from e in emps    select new {o.OrderID, e.FirstName};

Order By操作

 

适用场景:对查询出的语句进行排序,比如按时间排序等等。

说明:按指定表达式对集合排序;延迟,默认是升序,加上descending表示降序,对应的扩展方法是OrderBy和OrderByDescending

1.简单形式

说明:默认为升序

var q =    from e in db.Employees    orderby e.HireDate    select e;

2.带条件形式

注意:Where和Order By的顺序并不重要。而在T-SQL中,Where和Order By有严格的位置限制。

var q =    from o in db.Orders    where o.ShipCity == "London"    orderby o.Freight    select o;

3.降序排序

var q =    from p in db.Products    orderby p.UnitPrice descending    select p;

4.ThenBy

说明:按多个表达式进行排序,例如先按City排序,当City相同时,按ContactName排序。

var q =    from c in db.Customers    orderby c.City, c.ContactName    select c;

说明:这一句用Lambda表达式像这样写:

var q = db.Customers.OrderBy(c => c.City).ThenBy(c => c.ContactName).ToList();

在T-SQL中没有ThenBy语句,其依然翻译为OrderBy,所以也可以用下面语句来表达:

var q = db.Customers.OrderBy(c => c.ContactName).OrderBy(c => c.City).ToList();

所要注意的是,多个OrderBy操作时,级连方式是按逆序。对于降序的,用相应的降序操作符替换即可。

var q = db.Customers.OrderByDescending(c => c.City).ThenByDescending(c => c.ContactName).ToList();

需要说明的是,OrderBy操作,不支持按type排序,也不支持匿名类。比如

var q = db.Customers.OrderBy(c => new {c.City,c.ContactName}).ToList();

会被抛出异常。错误是前面的操作有匿名类,再跟OrderBy时,比较的是类别。比如

var q = db.Customers.Select(c => new { c.City, c.Address }).OrderBy(c => c).ToList();

如果你想使用OrderBy(c => c),其前提条件是,前面步骤中,所产生的对象的类别必须为C#语言的基本类型。比如下句,这里City为string类型。

var q = db.Customers.Select(c=>c.City).OrderBy(c => c).ToList();

5.ThenByDescending

这两个扩展方式都是用在OrderBy/OrderByDescending之后的,第一个ThenBy/ThenByDescending扩展方法作为第二位排序依据,第二个ThenBy/ThenByDescending则作为第三位排序依据,以此类推

var q =    from o in db.Orders    where o.EmployeeID == 1    orderby o.ShipCountry, o.Freight descending    select o;

6.带GroupBy形式

var categories =    from p in db.Products    group p by p.CategoryID into g    orderby g.Key    select new {        g.Key,        MostExpensiveProducts =            from p2 in g            where p2.UnitPrice == g.Max(p3 => p3.UnitPrice)            select p2    };



本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2010/12/20/1911817.html,如需转载请自行联系原作者

目录
相关文章
|
SQL 开发框架 .NET
linq中left join和inner join的正确用法
linq中left join和inner join的正确用法
|
存储 .NET C#
C# LINQ 详解 From Where Select Group Into OrderBy Let Join
目录 1. 概述 2. from子句 3. where子句 4. select子句 5. group子句 6. into子句 7. 排序子句 8. let子句 9. join子句 10. 小结 1. 概述     LINQ的全称是Language Integrated Query,中文译成“语言集成查询”。
2131 0
|
自然语言处理 .NET
Linq使用Group By
1.简单形式: var q = from p in db.Products group p by p.CategoryID into g select g; 语句描述:Linq使用Group By按CategoryID划分产品。
3946 0
|
机器学习/深度学习 .NET
|
.NET 开发框架 数据库
深入调研Linq to Objects Join Linq to Entity
最近工作中遇到数据库组合查询带来的一些问题,因此有必要调研一下Linq to Objects Join Linq to Entity。参考一些网友的代码案例,深入实践了一下使用EntityFramework Code First 下的组合查询。
1256 0
|
.NET 开发框架
|
.NET 索引 开发框架