2011-03-09 66 views
2

我提出了一个相关的问题有关:
'Invalid column name [ColumnName]' on a nested linq query最大(X => x.Time)VS OrderByDescending(X => x.Time)。首先()时间

我试图让高层在这里问的一组行如下:
Linq - Top value from each group

但是,我接近它不同于接受的答案使用最大。我就是这么做的:

ATable 
    .GroupBy (t => t.ID) 
    .Select (t => t.OrderByDescending(x=>x.Timestamp).FirstOrDefault().Timestamp) 

这将导致错误SqlException: Invalid column name 'ID'

现在,当我使用最多的功能:

ATable 
    .GroupBy (t => t.ID) 
    .Select (t => t.Max(x=>x.Timestamp)) 

它返回的,我想时间列表。

我的理解是,他们是不同的,但同等的要求。为什么我在第一次调用时遇到sql错误?

更新
第一个查询生成的SQL查询看起来是这样的:

SELECT (
    SELECT [t3].[Timestamp] 
    FROM (
     SELECT TOP 1 [t2].[Timestamp] 
     FROM [ATable] AS [t2] 
     WHERE (([t1].[ID] IS NULL) AND ([t2].[ID] IS NULL)) OR (([t1].[ID] IS NOT NULL) AND ([t2].[ID] IS NOT NULL) AND ([t1].[ID] = [t2].[ID])) 
     ORDER BY [t2].[Timestamp] DESC 
     ) AS [t3] 
    ) AS [value] 
FROM (
    SELECT [t0].[ID] 
    FROM [ATable] AS [t0] 
    GROUP BY [t0].[ID] 
    ) AS [t1] 

我设法降低下来,但保持了同样的错误:

SELECT (
    SELECT [t3].[Timestamp] 
    FROM (
     SELECT TOP 1 [Timestamp] 
     FROM [ATable] 
     WHERE [t1].[ID] = [ID] 
     ) AS [t3] 
    ) AS [value] 
FROM (
    SELECT [ID] 
    FROM [ATable] 
    GROUP BY [ID] 
    ) AS [t1] 

UPDATE2
有些答案说,这些查询在逻辑上是不同的,但是,如果你做这样的事情在罗斯文表,它会产生相同的结果:

OrderDetails 
    .GroupBy(x=>x.ProductID) 
    .Select(x=>x.OrderByDescending(y=>y.UnitPrice).FirstOrDefault().UnitPrice).Dump(); 

OrderDetails 
    .GroupBy(x=>x.ProductID) 
    .Select(x=>x.Max(y=>y.UnitPrice)).Dump(); 

所以我不能接受任何3个答案是说,查询是不同的,或者最多是给点心代替的列表的最大值,或者在继续之前必须将IQueriable转换为列表。

+0

你能以某种方式让我为第一个查询生成的SQL查询吗? serverlogs应该有他们。 – Femaref 2011-03-09 02:17:27

+0

作为对所提供答案的回应,如果您遵循第二个链接,则会提供使用OrderByDescending但不链接.Timestamp或一般链接的解决方案(不接受)。[FieldID]。这将回馈第一行..但链接领域不工作(即使与FirstOrDefault)。 – Joe 2011-03-09 02:18:57

+0

如果它没有链接'时间戳',那么两个查询之间必定有一个主要区别。 – Femaref 2011-03-09 02:20:44

回答

4

更新2:我只是想对此作出回应:

however, if you do something like this on the northwind table, it will produce the same result [...] So I cannot accept any of the 3 answers that say the queries are different

我并不想否认,他们应该产生相同的结果。为了更好地说明我的观点,让我提供一个比喻。

比方说,我给你一堆从1到50的索引卡片,然后我说:“把这些全部整理好。”所以,你要经过并整理出来,确保这个桩从1到50。这需要你一两分钟。 然后我说:“现在把卡片放在堆的顶部。”这张卡片恰好是编号为50的卡片。

另一方面,假设首先我说的是“给我这张卡片上最高的数字”。然后,你要做的就是通过卡片找到数量最多的卡片,而无需进行任何分类。 (我的意思是,你可能首先排序桩,但这显然会比我问的做得更多。)

所以我说的是结果以上两组指令是一样的;然而,他们显然是不同的指示

现在,如果某些实现具有足够的智能以将它们翻译成相同(优化的)SQL查询,那么它根本不会让我感到意外;我想说的是,既然他们不同说明,它不应该是那么令人惊讶,如果生成的SQL是不同的(尽管它可能是不幸,它因此也不算太奇怪,一个版本可以当另一个不会导致错误)。


更新:同样,我真的不能给你的LINQ到SQL方面的详细回应;但我会指出,尽管Max理论上应该产生相同的结果作为OrderByDescending连同FirstOrDefault,但从概念的角度来看,它不是真的一样。

考虑Linq-to-objects。调用Max将遍历序列并累积最大值。调用OrderByDescending排序整个序列然后占据首位。

显然,Linq-to-SQL是另一种动物;然而,它是有道理的,因为这些查询代表概念上不同的方法来获得一定的结果,他们产生的SQL很可能(并且,正如你所看到的,)不同。


原来的答案

我真的不能给你的LINQ到SQL方面的详细回应,但我会指出,有你两个选择之间存在非常严重分歧(他们是当量):

Max(x => x.Timestamp) 

以上应返回最大的时间戳

OrderByDescending(x => x.Timestamp()).FirstOrDefault() 

以上应返回记录以最大的时间戳

这些是非常不同的野兽。

+0

实质上,两者是相同的,但他可以简单地在'FirstOrDefault'调用之后链接'.Timestamp',问题应该是将表达式树翻译为一个sql语句。 – Femaref 2011-03-09 02:11:55

+0

我的不好,我实际上链接'.Timestamp'来得到错误,只是得到FirstOrDefault()不会给我错误。现在更新问题。 – Joe 2011-03-09 02:14:50

+0

@Femaref:他*可以*做到这一点(也许他做到了);我只是想,我应该指出这一点,以防万一OP出现了'Max'这个错误的印象(我知道我犯了一个错误,认为它会返回记录*,并且最多不止一次) 。 – 2011-03-09 02:15:25

相关问题