2017-06-10 2 views
0

Ich habe durch einige relevante Verschmelzen Fragen gegangen, aber mein Problem ist, aus den bestehenden etwas anders. Ich habe eine Tabelle in meiner PostgreSQL 9.5-Datenbank, die vier Spalten enthält, d. H. Segment (eindeutige Gruppe), Höhe (numerisch), Untergrenze (numerisch) und Obergrenze (numerisch). Die Beispieldaten sind wie folgt:Wie kann ich Zeilen basierend auf Zeilenunterschieden in PostgreSQL bedingt zusammenführen?

Segment height lower_limit upper_limit 
A  19.3 112   142 
A  19.3 142   172 
A  20.3 172   202 
A  20.3 202   232 
A  19.3 232   262 
A  19.3 262   292 
B  22.1 203   233 
B  22.1 233   263 
B  22.1 263   293 
B  22.1 293   323 
B  22.1 323   353 
B  22.1 353   383 
C  18.9 136   166 
C  18.9 166   196 
C  18.9 196   226 
C  27.1 286   316 
C  27.1 316   346 
C  6.5  346   376 
C  6.5  376   406 

Ich muss Zeilen basierend auf dem Unterschied der Höhe Werte bedingt zusammenführen. Ich würde versuchen, in Schritten zu erklären:

  • Ausgehend von der ersten Höhe, ob die Differenz zwischen dem vorhergehenden und dem Zeilenfolgenden weniger oder gleich 1
  • Wenn Bedingung der Zeilen mit Untergrenze der ersten Reihe erfüllt fusionieren und die obere Grenze der fusionierten Reihe
  • , wenn alle Zeilen in einer Gruppe zusammengefasst werden dann wählen Sie die am häufigsten Höhe mit Untergrenze der ersten und obere Grenze der letzten fusionierten Reihe
  • wiederholen dies für andere Gruppen

    Basierend o n oben könnte die gewünschte Ausgabe wie:

    Segment height lower_limit upper_limit A 19.3 112 292 B 22.1 203 383 C 18.9 136 226 C 27.1 286 346 C 6.5 346 406

Kann jemand mir helfen, so dass ich bedingt Zeilen basierend auf Höhendifferenzwert verschmelzen könnte?

+0

gibt es eine Spalte die Reihenfolge angeben können? –

+0

Ich habe am Ende des Codes eine Bestellung von grp line hinzugefügt. Ich bekomme 5 Zeilen entsprechend der gewünschten Ausgabe, aber auf diese Weise: C, A, B, C, C. Bitte sehen Sie die gewünschte Ausgabe. –

+0

Reihenfolge hinzufügen durch 'segment, grp' –

Antwort

1

Unter der Annahme, lower_limit Spalte kann für die Bestellung verwendet werden, Sie

select segment,mode() within group(order by height),min(lower_limit),max(upper_limit) 
from (select t.* 
     ,sum(case when abs(height-prev) <= 1 then 0 else 1 end) over(partition by segment order by lower_limit) as grp 
     from (select t.* 
      ,lag(height) over(partition by segment order by lower_limit) as prev 
      from tbl t 
      ) t 
    ) t 
group by segment,grp 
+0

Ich habe die letzten zwei Zeilen geändert. Ich habe hinzugefügt: group by grp, segment Order by grp, segment. Ich habe A, B, C, C, C wie gewünscht. Alle Werte sind gut, mit Ausnahme des ersten Segments A. Für A; es gibt, 20.3, 112, 292. Irgendeine Idee warum? –

+0

@JibranKhan ..check die edit..using 'mode' Sie die häufigste Höhe pro Segment und grp..which gibt, ist, was Sie brauchen. –

+0

Vielen Dank –

1
-- setting reset points 
    with b as 
    (
     select segment, height, lower_limit, upper_limit, 
      case when lag(height) over (partition by segment order by segment, height) is null 
         or abs(height - lag(height) over (partition by segment order by segment, height)) > 1 
        then 1 end as is_reset 
     from foo 
) 
    -- setting groups 
    , c as 
    (
     select segment, height, lower_limit, upper_limit, 
       sum(is_reset) over (order by segment, height) as grp 
     from b 
    ) 
     -- finding most common height 
      select segment, mode() within group (order by height), 
        min(lower_limit) as lower_limit, 
        max(upper_limit) as upper_limit 
      from c 
      group by segment, grp 
 
segment | mode | lower_limit | upper_limit 
:------ | ----: | ----------: | ----------: 
A  | 19.30 |   112 |   292 
B  | 22.10 |   203 |   383 
C  | 6.50 |   346 |   406 
C  | 18.90 |   136 |   226 
C  | 27.10 |   286 |   346 

dbfiddle here

+0

Vielen Dank. Ich habe Ihren Code in dbfiddle getestet. Es hat dort gut funktioniert. Genau dieselbe Tabelle ist in meiner Postgres db, aber sie hat sechs Zeilen zurückgegeben, d. H. A, B, C, C, C, C. Eine Zeile C (18,9, 136, 226) wird zweimal zurückgegeben. Irgendeine Idee warum? –

+0

führen Sie die erste Auswahl aus und stellen Sie sicher, dass sie die richtige Reihenfolge zurückgibt. – McNets

+0

Nun, ich habe den ganzen Code neu formatiert, um sicherzustellen, dass ich keinen Fehler mache, aber immer noch dasselbe Ergebnis. –

Verwandte Themen