使用Linq to SQL,如何在表中找到列的最小值和最大值?

我想找到一种最快的方法来获取表中的列的最小值和最大值,并使用单个Linq to SQL往返。 所以我知道这将在两个往返中起作用:

int min = MyTable.Min(row => row.FavoriteNumber); int max = MyTable.Max(row => row.FavoriteNumber); 

我知道我可以使用group但是我没有group by子句,我想聚合整个表! 如果没有先分组,我就不能使用.Min。 我试过这个:

 from row in MyTable group row by true into r select new { min = r.Min(z => z.FavoriteNumber), max = r.Max(z => z.FavoriteNumber) } 

但是这个疯狂的组子句似乎很愚蠢,而它所做的SQL比它需要的更复杂。

那么,有没有办法让正确的SQL出来?

编辑:这些家伙也失败了: Linq to SQL:如何在没有小组的情况下聚合? ……如果真的没有答案,LINQ设计师的疏忽。

编辑2:我在SQL Server Management Studio执行计划分析中查看了我自己的解决方案(使用无意义的常量group by子句),它在我看来它与生成的计划完全相同:

 SELECT MIN(FavoriteNumber), MAX(FavoriteNumber) FROM MyTable 

因此,除非有人能够提出一个更简单或同样好的答案,否则我认为我必须将其标记为自己回答。 思考?

正如问题中所述,这种方法似乎实际上生成了最佳的SQL代码,因此虽然它在LINQ中看起来有点松懈,但它应该是性能最佳的。

 from row in MyTable group row by true into r select new { min = r.Min(z => z.FavoriteNumber), max = r.Max(z => z.FavoriteNumber) } 

我发现只有这个产生一些干净的sql仍然没有真正有效,相比于表中的select min(val),max(val):

 var r = (from min in items.OrderBy(i => i.Value) from max in items.OrderByDescending(i => i.Value) select new {min, max}).First(); 

sql是

 SELECT TOP (1) [t0].[Value], [t1].[Value] AS [Value2] FROM [TestTable] AS [t0], [TestTable] AS [t1] ORDER BY [t0].[Value], [t1].[Value] DESC 

仍然有另一种选择为最小和最大查询使用单一连接(请参阅多个活动结果集(MARS) )

或存储过程..

我不知道如何将它翻译成C#(我正在研究它)

这是Haskell版本

 minAndMax :: Ord a => [a] -> (a,a) minAndMax [x] = (x,x) minAndMax (x:xs) = (min ax, max bx) where (a,b) = minAndMax xs 

C#版本应该涉及Aggregate一些(我认为)。

LINQ to SQL查询是单个表达式。 因此,如果您无法在单个表达式中表达您的查询(或者您不喜欢它),那么您必须查看其他选项。

存储过程,因为它们可以有语句,使您能够在一次往返中完成此操作。 您将具有两个输出参数或选择具有两行的结果集。 无论哪种方式,您都需要自定义代码来读取存储过程的结果。

(我个人认为没有必要避免在这里进行两次往返。这似乎是一种过早的优化,特别是因为你可能不得不跳过箍来使其工作。更不用说你花费时间来certificate这个决定的合理性并向其他开发人员解释解决方案。)

换句话说:你已经回答了自己的问题。 “我不能在没有分组的情况下使用.Min”,其次是“疯狂的群组条款似乎很愚蠢,而且它制作的SQL比它需要的更复杂”,是简单易懂的两条线索 – 往返解决方案是您意图的最佳表达(除非您编写自定义SQL)。

您可以选择整个表,并在内存中执行最小和最大操作:

 var cache = // select * var min = cache.Min(...); var max = cache.Max(...); 

根据数据集的大小,这可能是不多次访问数据库的方法。