Запрос Linq: МАКСИМАЛЬНЫЙ в ГДЕ - PullRequest
1 голос
/ 25 августа 2011

У меня длинный запрос, который возвращает

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 query:

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 голосов
/ 25 августа 2011

так, что если entryDate> = 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.

Сказав это, вы просто хотите выбрать значение. Значение, соответствующее каждому элементу вашего запроса.Каждый элемент должен искать соответствующее значение, соответствующее вашему выражению 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 Profiler, чтобы быть уверенным.

0 голосов
/ 25 августа 2011

Если вы вернули свои данные из запроса 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очень полезно и часто упускается из виду.

0 голосов
/ 25 августа 2011
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
                              });

Отфильтруйте запрос, объедините два элемента в один и измените первый элемент

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...