Linq查询:在WHERE中的MAX

时间:2011-08-24 21:45:00

标签: linq linq-to-sql

我有一个长的查询返回

Item {
    DateTime entryDate
    .....
}

我喜欢将此查询的结果与另一个表

结合起来
Value {
    DateTime date,
    double value
}

如果entryDate> = CUTOFF,则取CUTOFF上的值,否则取entryDate上的值。换句话说,我想实现:

 SELECT Item.*, Value.value WHERE
 MIN( Item.entryDate, CUTOFF ) == Value.date

请原谅我的语法,但这就是主意。

编辑:经过一些试验和错误,我想出了这个linq-to-sql查询:

from iValue in Values
join iItem in ... (long query)
let targetDate = iItem.EntryDate > CUTOFF ? iItem.EntryDate : CUTOFF
where iValue.Date == targetDate
select new
{
    iItem,
    targetDate,
    iValue    
}

感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

yourLongQuery.Where(y => y.Item.entryDate == Value.date || CUTOFF == Value.date)
             .Select(x => new { 
                              entrydate = (x.Item.entryDate < CUTOFF ? x.Item.entryDate : CUTOFF), 
                              /*rest of x.Item properties here */ , 
                              x.Value.date, 
                              x.Value.value
                              });

过滤查询,将两个项目合并为一个项目并修改第一个项目

答案 1 :(得分:0)

  

这样如果entryDate&gt; = CUTOFF,则取CUTOFF上的值,否则   在entryDate上取值。换句话说,我想实现:   SELECT Item。*,Value.value WHERE MAX(Item.entryDate,CUTOFF)==   Value.date

这是自相矛盾的if entryDate >= CUTOFF then take the value on CUTOFF实施,您需要MIN(Item.entryDate, CUTOFF),而不是MAX

话虽如此,您只想选择与查询的每个项目匹配的value.Value。每个项目都应查找与您的MAX(或我相信MIN)语句匹配的相关值。

query.Select(item =>
{
    var matchingValue = Values.Single(v => 
        v.date == Min(item.entryDate, CUTOFF));
    return new { item, matchingValue.value };
});

这将返回IQueryable的匿名{ Item, double }个对象。


如果您要求将其作为单个SQL语句执行,则需要进行一些重构。一个好的开始是将matchingValue交换成一个声明。

query.Select(item => new { item, context.Values.Single(v => 
    v.date == Min(item.entryDate, CUTOFF)).value });

我没有在我面前确认Visual Studio,但我不确定Math.Min函数是否在LINQ-to-SQL中映射。我们假设它不是。

query.Select(item => new { item, context.Values.Single(v => 
    v.date == (item.entryDate < CUTOFF ? item.entryDate : CUTOFF)).value });

我相信如果您使用.ToList()执行该查询,将解析为单个查询,但在我面前有一些工具之前无法确认。使用SQL事件探查器进行测试以确定。

答案 2 :(得分:0)

鉴于您已从Item查询中返回数据并且Value表格相对较小,那么这是一个不错的方法:

var lookup = values.ToLookup(v => v.date, v => v.value);

var query =
    from i in items
    let c = i.entryDate < CUTOFF ? i.entryDate : CUTOFF
    let v = lookup[c].FirstOrDefault()
    select new
    {
        Item = i,
        Value = v,
    };

ToLookup扩展程序非常有用且经常被忽略。