2017-01-11 6 views
1

Ich habe eine sehr einfache geordnete Tabelle mit den folgenden Daten:Wie GROUP BY ohne Reihenfolge zu brechen?

============================= 
| 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  | 
============================= 

Ich würde [Timestamp], um mögen SELECT MAX([Timestamp]), Count FROM [dbo].[Table] GROUP BY [Count], ohne zu brechen, dh der Ausgang sein soll:

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

So ist 12/1/2016 | 322 nicht verborgen durch die GROUP BY. Weiß jemand, wie man solche Frage schreibt? Ich brauche eine EntityFramework Linq-Abfrage und es wäre toll, ein T-SQL-Analog zu kennen.

+0

Gruppe von Count und geting max funktioniert nicht?!? – Damirchi

+0

@Damirchi nein, weil es den zweiten '322' Wert verstecken wird – dyatchenko

+0

Sie sagten" max Zeitstempel für jede Zählung "und dort am meisten eins 322 nicht mehr – Damirchi

Antwort

3

Ich glaube, Sie brauchen eine Abfrage wie folgt:

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; 
+0

Sieht aus wie diese Abfrage funktioniert perfekt! Danke vielmals. Kennst du ein Linq-Analog? – dyatchenko

+0

Ich bin nicht wirklich gut in LinQ, aber jetzt können Sie nach einem LinQ für diese Abfrage fragen;). –

0

ich vorherige Antwort zu sehen, und auf der Grundlage seiner schriftlichen LINQ Anfrage.

1) Erstellen Sie 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) Add Zeilenindex in initTable und Reihenfolge von Zeitpunkt:

//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) Abfrage

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 
      }); 

Sie können es in LinqPad einfügen und das Ergebnis überprüfen.

Ich hoffe, dass dies hilfreich sein wird.