Collectionの中から効率よく目的のデータを取得したい


次のようなコレクションがあったとします。

[code]

    List<Item> itemlist = new List<Item>();
    itemlist.Add(new Item(){Id = 1, Name = "A"});
    itemlist.Add(new Item(){Id = 2, Name = "B"});
    itemlist.Add(new Item(){Id = 3, Name = "C"});
    
    class Item
    {
      int Id {get;set;}
      string Name{get;set;}
      int value {get;set;}
    }
    
[/code]

また、SQL Serverのテーブルには以下のレコードが10M件あるとします。

[code]

    ------------------------
    |Id | DateTime | Value |
    ------------------------
    |1 | 2017-09-26 13:03 | 9|
    ------------------------
    |1 | 2017-09-26 13:03 | 5|
    ------------------------
    |1 | 2017-09-26 13:03 | 2|
    ------------------------
    .
    .
    .
    |3 | 2017-01-01 00:01 | 11|
    ------------------------
    
[/code]

このデータベースから該当Itemの最新データを取得する効率のよい方法をご教授いただきたいです。

[code]

    foreach(var n in itemlist)
    {
     n.value = table.where(c=>c.Id = n.Id).OrderByDescending(c=>c.DateTime).Select(c=>c.value).FirstOrDefault();
    }
    
[/code]

この方法で取得すると、レコードが多い場合、OrderbyDescendingがあるせいかとても遅くなります。。

何か他によい方法がございますでしょうか。

.NET Framework4.0の環境で開発しています。  
よろしくお願いします。




htbさんの

> Idで集計(`group by [Id]`)した結果を利用する

ですがコードで書くと

[code]

    var idValue = table
        .GroupBy(c => c.Id, (Id, g) => new { Id, DateTime = g.Max(c => c.DateTime) })
        .Join(table, id => id, c => new { c.Id, c.DateTime }, (_, c) => new { c.Id, c.Value })
        .ToDictionary(c => c.Id, c => c.Value);
    
[/code]

とすることで`Id => Value`のマッピング辞書を構築できます。あとは

[code]

    foreach(var n in itemlist)
        n.value = idValue[n.Id];
    
[/code]

と辞書を引くだけです。




htbさんの

> Idで集計(`group by [Id]`)した結果を利用する

ですがコードで書くと

[code]

    var idValue = table
        .GroupBy(c => c.Id, (Id, g) => new { Id, DateTime = g.Max(c => c.DateTime) })
        .Join(table, id => id, c => new { c.Id, c.DateTime }, (_, c) => new { c.Id, c.Value })
        .ToDictionary(c => c.Id, c => c.Value);
    
[/code]

とすることで`Id => Value`のマッピング辞書を構築できます。あとは

[code]

    foreach(var n in itemlist)
        n.value = idValue[n.Id];
    
[/code]

と辞書を引くだけです。

