LINQ查询或存储过程以返回指定列中的最大值

时间:2009-07-02 14:41:56

标签: linq-to-sql stored-procedures dynamic-linq

表格如

datetime          a1   b1   x2 ...  
07-01-2009 13:10   8    9    10  
07-01-2009 13:11   8    8    2  
07-01-2009 13:12   9    1    1    

一整天每秒1行(= 86400行); ~40列;所有相同的格式
我正在寻找一种方法来检索最大值和列指定的时间。

我正在寻找一种方法来检索列的最大值和相应时间,以便在时间范围内指定。

这样的东西
Select top 1 time,a1 from table
    where (datetime>=begin and datetime<end) 
    order by a1 desc   

可以使用,但我不能将该列用作参数。

LINQ解决方案或SP会很棒。

排序整个数据集以检索最大值时,是否必须担心性能?也许MAX功能会更快。

更新

我试图以动态的linq方式实现它,就像Timothy(tvanfossen)建议的那样

Dim q2 = context.table _
  .Where("t >= @0 AND t < @1", begin, end) _
  .OrderBy("@0 desc", col) _
  .Take(1) _
  .Select(col)

但这会返回表格中的第一个值。 这将返回时间范围中的第一个值,而不是最大值。查看SQL分析器,我发现没有ORDER子句 任何的想法?

更新2
由于某种原因,替换值在orderby子句中不起作用 .OrderBY(col +“desc”)工作

4 个答案:

答案 0 :(得分:2)

在SQL中:

select max(a1)
from table
where (datetime>=begin and datetime<end) 

您不需要排序,只需使用标准聚合函数。为了能够动态选择列,您需要动态创建SQL,并使用字符串连接,但要非常小心以确保列名实际上是列名,而不是SQL注入。

在LINQ中,再次使用聚合:

var res = datacontext.Table
                     .Where(t => t.datetime >= begin && t.datetime < end)
                     .Max(t => t.a1);

传递给Max的lambda表达式选择列以获得最大值。要处理动态选择的列,有两个路径:

首先,您可以将片段构建为片段,如果有一小组固定的列,则很好:

Expression<Func<TableType, ColumnType>> colSelector = null;
switch (column) {
  case "a1":
    colSelector = t => t.a1;
    break;
  case "b2":
    colSelector = t => t.b2;
    break;
  ...
}
var res = datacontext.Table
                     .Where(t => t.datetime >= begin && t.datetime < end)
                     .Max(colSelector);

或者,第二个选项:使用表达式API自己构建表达式。有关详细信息,请参阅此处:http://www.albahari.com/nutshell/predicatebuilder.aspx

答案 1 :(得分:1)

如果您希望列名称是动态的,则可能需要使用Dynamic Linq中的VS2008 code samples。然后,您可以指定要排序的列的名称。

var query = context.table
                   .Where( t = t.begin <= date && date < t.end )
                   .OrderBy( "a1 desc" )
                   .Take(1)
                   .SingleOrDefault();

答案 2 :(得分:0)

我认为这会奏效。基本上使用函数来返回列的顺序。

var result = Table
                .OrderByDescending( row => GetColumnOfInterest(row) )
                .First()
                .dateTime;

int GetColumnOfInterest( Row row )
{
   if ( ... )
   {
      return row.a1;
   }
   else if ( ... )
   {
      return row.b1;
   }
}

答案 3 :(得分:0)

怎么样:

IEnumerable<Table> results = Table;

switch ( condition )
{
    condition 1:
        results = results.OrderByDescending( row => row.a1 );
    condition 2:
        results = results.OrderByDescending( row => row.a2 );
    condition 3:
        results = results.OrderByDescending( row => row.a3 );

    ....

}

var result = results.First().dateTime;