Linq Group By - 将每个组中的单个记录选择为键入的结果

时间:2010-11-16 19:15:35

标签: linq linq-to-sql

以下是查询类似于我想要实现但简化的。 在我的实际代码中,我有四个表连接并尝试获得其中包含最新版本的结果。我有C#版本我非常接近,但无法创建类型结果集

的Vb版本

C#版 此查询生成我想要的适当的sql,但无法选择我需要的列。

var query= from user in Customers join adrs in CustomerAddress
             on user.Id equals adrs.CustId
             group user by adrs.CustId into g
             select g.OrderByDescending(x=>x.adrs.Version).First();

VB版 此查询按顺序失败并调用First在后面生成糟糕的SQL

dim query= from user in Customers Join adrs in CustomerAddress _
              on user.Id Equals adrs.CustId _
           Group By custId=adrs.CustId Into g = Group _
           Order By adrs.version Descending _
           Let latestAddress=g.First() _
           Select new ResultObject() with _
           { _
           .AddressId=latestAddress.adrs.Id, _
           .Street=latestAddress.adrs.Street _
               }

dim results=query.ToList()

- 更新

我正在寻找与此类似的SQL,它是由上面的C#查询生成的,除了我想选择列名。

SELECT [t3].[test], [t3].[ID], [t3].[RequestQueueId], [t3].[CI_RequestType], [t3].[CI_Division], [t3].[CI_Company], 
FROM (
    SELECT [t0].[RequestQueueId]
    FROM [RequestHeader] AS [t0]
    GROUP BY [t0].[RequestQueueId]
    ) AS [t1]
OUTER APPLY (
    SELECT TOP (1) 1 AS [test], [t2].[ID], [t2].[RequestQueueId], [t2].[CI_RequestType], [t2].[CI_Division], [t2].[CI_Company], 
    FROM [RequestHeader] AS [t2]
    WHERE [t1].[RequestQueueId] = [t2].[RequestQueueId]
    ORDER BY [t2].[Version] DESC
    ) AS [t3]
ORDER BY [t3].[Version] DESC

2 个答案:

答案 0 :(得分:1)

对于初学者,如果您非常喜欢sql,则可以使您的VB版本与您的c#版本相同,因为您想要的列将在c#版本返回的对象上可用。我对查询语法不太满意,但我认为它类似于:

Dim query = From user In Customers Join adrs In CustomerAddress _
    On user.Id Equals adrs.CustId _
    Group user By adrs.CustId Into g _ 
    Select g.OrderByDescending(Function(x) x.adrs.Version).First()

然而,一个可能的流畅版本将是:

<强> C#

    var query = Customers
    .Join(
     CustomerAddress,
     x => x.Id,
     x => x.CustId,
     (o,i) => i
    ).GroupBy(x => x.CustId)
    .SelectMany(x => x
     .OrderByDescending(y => y.version)
     .First()
    ).Select(x => new ResultObject() {
     AddressId = x.Id,
     Street = x.Street
    });

<强> VB

    Dim query = Customers _
    .Join( _
     CustomerAddress, _
     Function(x) x.Id, _
     Function(x) x.CustId, _
     Function(o,i) i _
    ).GroupBy(Function(x) x.CustId) _
    .SelectMany(Function(x) x _
     .OrderByDescending(Function(y) y.version) _
     .First() _
    ).Select(Function(x) New ResultObject() With { _
     .AddressId = x.Id, _
     .Street = x.Street _
    })

注意:上面的代码未经测试,但我希望它有所帮助!

答案 1 :(得分:0)

我想这会解决你的问题

var query =
from customeraddress in db.CustomerAddresses
join customers in db.Customers on new { CustId = customeraddress.CustId } equals new { CustId = customers.Id }
join LatestVersion in
    (
        (from customeraddress_1 in db.CustomerAddresses
            group customeraddress_1 by new
            {
                customeraddress_1.CustId
            } into g
            select new
            {
                CustId = (System.Int32)g.Key.CustId,
                MaxVersion = (System.Int32)g.Max(p => p.Version)
            }))
        on new { customeraddress.CustId, customeraddress.Version }
    equals new { CustId = Convert.ToInt32(LatestVersion.CustId), Version = Convert.ToInt32(LatestVersion.MaxVersion) }
select new
{
    Id = (System.Int32)customers.Id,
    customers.Field1,
    customers.Field2,
    customeraddress.Field3,
    customeraddress.Field4,
    Version = (System.Int32)customeraddress.Version
};
var results = query.ToList();