Top 5 Werte pro Monat abfragen

winscheil

Aktiver Benutzer
Beiträge
25
Hallo,
ich möchte eine Abfrage bauen, die mir aus einer Tabelle immer die 3 höchsten Werte jedes Monats ausgibt.
Datenaufbau:
Monat Wert
01 550
01 200
01 320
01 600
01 120
02 800
02 410
02 150
02 590
02 730
...

Die Ausgabe soll dann folgendes bringen:
Monat Wert
01 600
01 550
01 320
02 800
02 730
02 590
...
Ich kann zwar mit Top 3 die drei höchsten Werte einer ganzen Tabelle ausgeben.
Aber ich weiß nicht, wie ich die Wiederholung für jeden Monat umsetzen kann.
Kann mir da jemand helfen?
 
Werbung:
via LATERAL JOIN:

Code:
edb=*# select * from winscheil ;
 monat | wert
-------+------
     1 |  550
     1 |  200
     1 |  320
     1 |  600
     2 |  800
     2 |  410
     2 |  150
     2 |  590
     2 |  730
(9 rows)

edb=*# select w.* from winscheil w left join lateral (select * from winscheil w2 where w2.monat = w.monat order by wert desc limit 2) x on (w.monat=x.monat and w.wert=x.wert) where x.monat is not null order by w.monat, w.wert;
 monat | wert
-------+------
     1 |  550
     1 |  600
     2 |  730
     2 |  800
(4 rows)

edb=*#
 
vielen Dank für die schnelle Antwort.
Das ist leider MSSQL. Da funktioniert LIMIT nicht.
Und leider kenne ich das left join lateral auch nicht... funktioniert das bei MSSQL?
 
Hallo winscheil,

ja Left Join funzt auch im SQL-Server. :)
Anstatt Limit nach DESC, nimmst du TOP 2 im SELECT. Beispiel: SELECT TOP 2 * FROM deine_tabelle usw
 
Hallo winscheil,

ja Left Join funzt auch im SQL-Server. :)
Anstatt Limit nach DESC, nimmst du TOP 2 im SELECT. Beispiel: SELECT TOP 2 * FROM deine_tabelle usw

Alternative Methode: mit row_number arbeiten, via 'partition my monat order by wert desc'. Nachteil: das wird komplett ausgeführt, während der LATERAL JOIN ... besser optimiert werden kann.
 
Code:
edb=*# with tmp as (select monat, wert, row_number() over (partition by monat order by wert desc) from winscheil) select monat, wert from tmp where row_number <= 2 order by monat, wert desc;
 monat | wert
-------+------
     1 |  600
     1 |  550
     2 |  800
     2 |  730
(4 rows)

wie gesagt, Nachteil wäre daß bei z.B. 1000 Werten je Monat alle gezählt und materilisiert werden (im CTE), dann aber 998 verworfen werden ...
 
was genau ist CTE?

Ich hab jetzt mal den Select übernommen:
with tmp as (select AUFTRAG,JAHR, KALENDERWOCHE, FINALE_KOSTEN, row_number() over (partition by AUFTRAG, JAHR, KALENDERWOCHE order by FINALE_KOSTEN desc) from ANP_FT_KALK_BEST_DASHBOARD)
select AUFTRAG, JAHR, KALENDERWOCHE, FINALE_KOSTEN from tmp where row_number <= 2 and AUFTRAG = '207201' order by JAHR, KALENDERWOCHE, FINALE_KOSTEN desc

Da bekomme ich folgende Fehlermeldung:
Kein Spaltenname wurde für die Spalte 5 von "tmp" angegeben.

Ich muss nach Auftrag, Jahr und Kalenderwoche unterscheiden.
Finale_Kosten ist der Wert, den ich brauche.
Und hier die 2 höchsten Werte in jeder Kalenderwoche von jedem Jahr, die in dem Auftrag sind.
Habe das mit Monat einfachhalber am Anfang erklärt...

Was mach ich bei der Abfrage falsch?
 
Werbung:
LATERAL dezent überlesen.... Sorry. Ja klar LEFT JOIN LATERAL im SQL-Server nein, aber LEFT JOIN ja :D
Microsoft hat sich entschieden den SQL Standard zu ignorieren, deswegen kochen sie ihr eigenen Süppchen und haben beschlossen dass "APLLY" besser ist als "LATERAL.

Das Äquivalent zu LEFT JOIN LATERAL in T-SQL ist deswegen OUTER APPLY
 
Zurück
Oben