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

Asked
Viewd1799

2

 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功能会更快。

更新

我试图像蒂莫西(tvanfossen)建议的那样以动态linq方式实现

 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 个答案

1

如果希望列名是动态的,则可能要使用动态Linq 来自 VS2008代码示例。然后,您可以指定要作为排序依据的列的名称。

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

我认为这会起作用。基本上使用函数将列返回排序。

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

int GetColumnOfInterest( Row row )
{
   if ( ... )
   {
      return row.a1;
   }
   else if ( ... )
   {
      return row.b1;
   }
}
 
  • @Alex:我认为这意味着必须在客户端上处理订单,LINQ to SQL无法将其转换为SQL。

    RichardJuly 02, 2009 15:25
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;
 
  • 这看起来与Richard的答案非常相似,他在那里构建了一个colSelector。

    Alex BlackJuly 02, 2009 17:11
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