LINQ to Entities中的分组/子查询与相关的未分组列

时间:2013-05-09 08:26:51

标签: sql-server entity-framework-4 linq-to-entities group-by

我在DB中有这个表:

ID    | Timestamp           | Score
------|---------------------|-------------------
1     | 2013-01-01 12:00:00 | 15
1     | 2013-01-02 11:00:00 | 1
1     | 2013-01-03 16:00:00 | 4
2     | 2013-01-08 04:00:00 | 7
2     | 2013-01-09 08:00:00 | 9
2     | 2013-01-10 11:00:00 | 6
3     | 2013-01-03 12:00:00 | 14
3     | 2013-01-01 10:00:00 | 15
3     | 2013-01-02 00:00:00 | 17

我需要的是每个ID的最后一个分数。 换句话说,对于每个ID,我需要选择时间戳最高的行,然后从该行获得分数。

我设法在SQL服务器中这样做(这可能不是最佳的)

SELECT ID, Timestamp, Score FROM Data cd
LEFT OUTER JOIN
    (SELECT ID as SubId, MAX(Timestamp) AS TS 
     FROM Data GROUP BY ID) AS SUB
ON cd.ID = SUB.SubId
WHERE Timestamp = TS

我需要一个LINQ to Entities(v4)解决方案来应对这种情况,但我不确定如何在这种情况下处理子查询和分组。

@Edit (回复评论): 我尝试了类似下面的内容,但我不知道如何从该分组项中获得分数,或者如何将子查询集成到此中。

from d in Datas
group d by d.ID into group
select new { ID = group.Key, TS = group.Max(i => i.Timestamp) }

这种情况可能吗?有没有更好的解决方案(性能方面)?

1 个答案:

答案 0 :(得分:0)

这应该达到你想要的效果:

from d in Datas
group d by d.ID into g
let maxDate = g.Max(d => d.Timestamp) 
select new 
{
    ID = g.Key, 
    Score = g.First(item => item.Timestamp == maxDate).Score
};

以下是我在LINQPad中使用的完整代码清单的副本:

void Main()
{
    var testData = GenerateTestData();

    var result = 
        from d in testData
        group d by d.ID into g
        let maxDate = g.Max(d => d.Timestamp) 
        select new 
        {
            ID = g.Key, 
            Score = g.First(item => item.Timestamp == maxDate).Score
        };

    foreach (var item in result)
    {
        Console.WriteLine("ID={0}; Score={1}", item.ID, item.Score);
    }
}

List<Item> GenerateTestData()
{
    List<Item> list = new List<Item>();
    list.Add(new Item(1, "2013-01-01 12:00:00", 15));
    list.Add(new Item(1, "2013-01-02 11:00:00", 1));
    list.Add(new Item(1, "2013-01-03 16:00:00", 4));
    list.Add(new Item(2, "2013-01-08 04:00:00", 7));
    list.Add(new Item(2, "2013-01-09 08:00:00", 9));
    list.Add(new Item(2, "2013-01-10 11:00:00", 6));
    list.Add(new Item(3, "2013-01-03 12:00:00", 14));
    list.Add(new Item(3, "2013-01-01 10:00:00", 15));
    list.Add(new Item(3, "2013-01-02 00:00:00", 17));
    return list;
}

class Item
{
    public Item(int id, string timestamp, int score)
    {
        ID = id;
        Timestamp = DateTime.Parse(timestamp);
        Score = score;
    }
    public int ID;
    public DateTime Timestamp;
    public int Score;
}

产生了输出:

ID=1; Score=4
ID=2; Score=6
ID=3; Score=14