优化Linq to SQL查询,Group By多个字段

时间:2010-07-26 19:57:08

标签: sql vb.net linq-to-sql

我的LINQ查询包含以下Group By语句:

Group p By Key = New With { _
.Latitude = p.Address.GeoLocations.FirstOrDefault(Function(g) New String() {"ADDRESS", "POINT"}.Contains(g.Granularity)).Latitude, _
.Longitude = p.Address.GeoLocations.FirstOrDefault(Function(g) New String() {"ADDRESS", "POINT"}.Contains(g.Granularity)).Longitude}

查询有效,但这是上面生成的子句生成的SQL

SELECT [t6].[Latitude]
            FROM (
                SELECT TOP (1) [t5].[Latitude]
                FROM [dbo].[GeoLocations] AS [t5]
                WHERE ([t5].[Granularity] IN (@p0, @p1)) AND ([t5].[AddressId] = [t2].[Addr_AddressId])
                ) AS [t6]
            ) AS [value], (
            SELECT [t8].[Longitude]
            FROM (
                SELECT TOP (1) [t7].[Longitude]
                FROM [dbo].[GeoLocations] AS [t7]
                WHERE ([t7].[Granularity] IN (@p2, @p3)) AND ([t7].[AddressId] = [t2].[Addr_AddressId])
                ) AS [t8]
            ) AS [value2]

我不是SQL专家,但我认为这是一个相当不理想的翻译。这应该是一个从第一条记录中选择Latitide和Longitude的查询。也许SQL Server Optimizer会处理这个问题。但有没有办法轻推Linq生成一个更精简的SQL语句?

我也试过以下......

Group p By Key = p.Address.GeoLocations.Where(Function(g) New String() {"ADDRESS", "POINT"}.Contains(g.Granularity)). _
Select(Function(g) New With {.Latitude = g.Latitude, .Longitude = g.Longitude}).FirstOrDefault

但这会产生错误:“group by expression只能包含服务器可比较的非常量标量。”

1 个答案:

答案 0 :(得分:1)

很抱歉回复c#...

这是你所拥有的,翻译成c#:

List<string> params = new List<string>()
{ "Address", "Point" };

from p in people
group p by new {
  Latitude = p.Address.GeoLocations
    .FirstOrDefault(g => params.Contains(g.Granularity)).Latitude,
  Longitude = p.Address.GeoLocations
    .FirstOrDefault(g => params.Contains(g.Granularity)).Longitude
};

这是使用let关键字重写的重写。

from p in people
let loc = p.Address.GeoLocations
   .FirstOrDefault(g => params.Contains(g.Granularity))
group p by new
{
  Latitude = loc.Latitude,
  Longitude = loc.Longitude
};