如何在没有违约的情况下进行GROUP BY?

时间:2017-01-11 05:46:35

标签: c# sql sql-server entity-framework linq-to-sql

我有一个非常简单的有序表,其中包含以下数据:

=============================
|   Timestamp  |    Count   |
=============================
|   12/30/2016 |    322     |
|   12/29/2016 |    322     |
|   12/28/2016 |    322     |
|   12/4/2016  |    541     |
|   12/3/2016  |    541     |
|   12/2/2016  |    541     |
|   12/1/2016  |    322     |
|   11/30/2016 |    322     |
|   11/29/2016 |    322     |
=============================

我希望SELECT MAX([Timestamp]), Count FROM [dbo].[Table] GROUP BY [Count]不要违反[Timestamp]顺序,即输出应为:

=============================
|   Timestamp  |    Count   |
=============================
|   12/30/2016 |    322     |
|   12/4/2016  |    541     |
|   12/1/2016  |    322     |
=============================

因此12/1/2016 | 322未隐藏GROUP BY。 有人知道怎么写这样的查询吗?我需要一个EntityFramework Linq查询,知道一个T-SQL模拟会很棒。

2 个答案:

答案 0 :(得分:3)

我认为您需要这样的查询:

select [Timestamp], [Count]
from (
    select *
        --//Step 3: Now just find the max value
        , row_number() over (partition by seqGroup order by [Timestamp] desc) as seq
    from (
        select *
            --//Step 2: you need to generate a group number for each sequence
            , sum(changed) over (order by [Timestamp] desc) as seqGroup
        from (
            select *
                --//Step 1: you need to track changes over [Count]
                , case when coalesce(lag([Count]) over (order by [Timestamp] desc), [Count]) = [Count] then 0 else 1 end as changed
            from yourTable ) t1
        ) t2
    ) t3
where seq = 1;

答案 1 :(得分:0)

我看到了之前的回答,并在他的基础上写了LINQ请求。

1)创建initTable:

var initTable = new List<Tuple<DateTime, int>>();
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 30), 322));
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 29), 322));
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 28), 322));
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 4), 541));
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 3), 541));
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 2), 541));
                initTable.Add(Tuple.Create(new DateTime(2016, 12, 1), 322));
                initTable.Add(Tuple.Create(new DateTime(2016, 11, 30), 322));
                initTable.Add(Tuple.Create(new DateTime(2016, 11, 29), 322));

2)在initTable中添加行索引并按时间戳排序:

//get row index
var table = initTable
            .Where(x => true)
            .Select((x, i) => new 
            {
                Timestamp = x.Item1.ToString("MM-dd-yyyy"), 
                Count = x.Item2,
                //row index
                Index = i
            })
            .OrderByDescending(x => x.Timestamp);

3)查询

var query = table
            //#1 get prev row count
            .Select(x => new
            {
                x.Timestamp,
                x.Count,
                x.Index,
                //previous row count (-1 for first row, not default null)
                Prev = table.LastOrDefault(y => y.Index < x.Index) == null ? 
                       -1 : 
                       table.LastOrDefault(y => y.Index < x.Index).Count
            })
            //#2 set group flag
            .Select(x => new
            {
                x.Timestamp,
                x.Count,
                x.Index,
                x.Prev,
                GroupId = x.Count == x.Prev
            })
            //#3
            .Where(x => x.GroupId == false)
            .Select(x => new
            {
                x.Timestamp,
                x.Count
            });

您可以将其插入LinqPad并验证结果。

我希望这会有所帮助。