web-dev-qa-db-ja.com

LINQ Max()を使用して単一の行を選択する

NHibernateから返されたIQueryableでLINQを使用しているため、いくつかのフィールドで最大値を持つ行を選択する必要があります。

こだわり続けている部分を簡略化しました。 1つのフィールドに最大値を持つテーブルから1つの行を選択する必要があります。

var table = new Table { new Row(id: 1, status: 10), new Row(id: 2, status: 20) }

from u in table
group u by 1 into g
where u.Status == g.Max(u => u.Status)
select u

これは正しくありませんが、正しいフォームを作成できません。

ところで、私が実際に達成しようとしているのは、ほぼこれです:

var clientAddress = this.repository.GetAll()
    .GroupBy(a => a)
    .SelectMany(
            g =>
            g.Where(
                a =>
                a.Reference == clientReference && 
                a.Status == ClientStatus.Live && 
                a.AddressReference == g.Max(x => x.AddressReference) && 
                a.StartDate == g.Max(x => x.StartDate)))
    .SingleOrDefault();

上記のラムダから始めましたが、LINQPadを使用してMax()を選択する構文を試しています。

UPDATE

GroupByを削除することが重要でした。

var all = this.repository.GetAll();

var address = all
            .Where(
                a =>
                a.Reference == clientReference && 
                a.Status == ClientStatus.Live && 
                a.StartDate == all.Max(x => x.StartDate) &&
                a.AddressReference == all.Max(x => x.AddressReference))
            .SingleOrDefault();
88
Boggin

ここでグループ化している理由がわかりません。

これを試して:

var maxValue = table.Max(x => x.Status)
var result = table.First(x => x.Status == maxValue);

tableを1回だけ反復する代替アプローチは次のようになります。

var result = table.OrderByDescending(x => x.Status).First();

これは、tableがメモリに存在しないか、オンザフライで計算されるIEnumerable<T>である場合に役立ちます。

206
Daniel Hilgarth

次のこともできます。

(from u in table
orderby u.Status descending
select u).Take(1);
14
KAPIL SHARMA

ステータスごとにグループ化し、最大のグループから行を選択できます。

table.GroupBy(r => r.Status).OrderByDescending(g => g.Key).First().First();

最初のFirst()は、最初のグループ(ステータスが最大の行のセット)を取得します。 2番目のFirst()は、そのグループの最初の行を取得します。
ステータスが常に一意である場合、2番目のFirst()Single()に置き換えることができます。

13
SLaks

最初の質問に対処し、特定の基準でグループ化された複数の行を最大値を持つ他の列と一緒に取得する必要がある場合、次のようなことができます:

var query =
    from u1 in table
    join u2 in (
        from u in table
        group u by u.GroupId into g
        select new { GroupId = g.Key, MaxStatus = g.Max(x => x.Status) }
    ) on new { u1.GroupId, u1.Status } equals new { u2.GroupId, Status = u2.MaxStatus}
    select u1;
7
Dmitry Komin

さらに1つの例:

フォロー:

 qryAux = (from q in qryAux where
            q.OrdSeq == (from pp in Sessao.Query<NameTable>() where pp.FieldPk
            == q.FieldPk select pp.OrdSeq).Max() select q);

等しい:

 select t.*   from nametable t  where t.OrdSeq =
        (select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)
0
SantanaFire