MS SQL niedrigster und höchster Datensatz einer Gruppe
Guten Morgen allerseits,
Tabelle BS beinhaltet alle bestellten Artikel (ArtikelNr, Belegdatum, Stückpreis, Menge, Rabatt). Alle ArtikelNr können mehrmals in dieser Tabelle zu finden sein.
Mein Ziel ist es von allen Artikeln den jeweils höchsten und niedrigsten Preis, inkl. der dazugehörigen weiteren Spalten, eines Artikels in einer Zeile darstellen zu können und dies auch noch gestaffelt nach Einkaufsjahr.
Das Ergebnis sollte folgendermaßen aussehen:
Nr | Jahr | Preis Max | Menge_Mx | Rabatt_Mx | Preis Min | Menge_Mn | Rabatt_Mn
Artikel1 | 2014 | 0,53 | 300,00 | 0 | 0,34 | 500,00 | 0
Artikel1 | 2015 | 0,67 | 300,00 | 0 | 0,60 | 500,00 | 10
Artikel1 | 2016 | 0,48 | 400,00 | 17,5 | 0,42 | 500,00 | 0
Artikel2 | 2014 | 5,00 | 5,00 | 0 | 4,50 | 5,00 | 0
Artikel2 | 2015 | 6,00 | 5,00 | 0 | 5,50 | 5,00 | 0
Artikel2 | 2016 | 7,00 | 5,00 | 0 | 6,50 | 5,00 | 0
Artikel3 | 2014 | 24,00 | 15,00 | 0 | 13,50 | 13,00 | 0
Artikel3 | 2015 | 24,00 | 18,00 | 0 | 24,00 | 14,00 | 0
Artikel3 | 2016 | 26,00 | 20,00 | 0 | 26,00 | 20,00 | 0
Über den Sinn der hier dargestellten Daten lässt sich streiten, aber sollte ausreichen, um zu veranschaulichen worauf meine Anfrage hinausläuft.
Bisher habe ich eine Abfrage gebastelt, die mir zwar die Ergebnisse liefert, aber unfassbar langsam ist (1 Minute und 10 Sekunden).
Siehe:
Puuh, wäre sehr dankbar, wenn mir jemand eine bessere Lösung aufzeigen könnte.
Vielen Dank vorab!
Tabelle BS beinhaltet alle bestellten Artikel (ArtikelNr, Belegdatum, Stückpreis, Menge, Rabatt). Alle ArtikelNr können mehrmals in dieser Tabelle zu finden sein.
Mein Ziel ist es von allen Artikeln den jeweils höchsten und niedrigsten Preis, inkl. der dazugehörigen weiteren Spalten, eines Artikels in einer Zeile darstellen zu können und dies auch noch gestaffelt nach Einkaufsjahr.
Das Ergebnis sollte folgendermaßen aussehen:
Nr | Jahr | Preis Max | Menge_Mx | Rabatt_Mx | Preis Min | Menge_Mn | Rabatt_Mn
Artikel1 | 2014 | 0,53 | 300,00 | 0 | 0,34 | 500,00 | 0
Artikel1 | 2015 | 0,67 | 300,00 | 0 | 0,60 | 500,00 | 10
Artikel1 | 2016 | 0,48 | 400,00 | 17,5 | 0,42 | 500,00 | 0
Artikel2 | 2014 | 5,00 | 5,00 | 0 | 4,50 | 5,00 | 0
Artikel2 | 2015 | 6,00 | 5,00 | 0 | 5,50 | 5,00 | 0
Artikel2 | 2016 | 7,00 | 5,00 | 0 | 6,50 | 5,00 | 0
Artikel3 | 2014 | 24,00 | 15,00 | 0 | 13,50 | 13,00 | 0
Artikel3 | 2015 | 24,00 | 18,00 | 0 | 24,00 | 14,00 | 0
Artikel3 | 2016 | 26,00 | 20,00 | 0 | 26,00 | 20,00 | 0
Über den Sinn der hier dargestellten Daten lässt sich streiten, aber sollte ausreichen, um zu veranschaulichen worauf meine Anfrage hinausläuft.
Bisher habe ich eine Abfrage gebastelt, die mir zwar die Ergebnisse liefert, aber unfassbar langsam ist (1 Minute und 10 Sekunden).
Siehe:
Select * from
(
Select distinct Z14.Artnr, Jahr = '2014',
P_Max = (Select MAX(Preis) From BS where Z14.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2015')),Q_Max = (Select TOP 1 Menge From BS where Preis = (Select MAX(Preis) From BS where Z14.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2015'))),
P_Min = (Select MIN(Preis) From BS where Z14.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2015')),Q_Min = (Select TOP 1 Menge From BS where Preis = (Select MIN(Preis) From BS where Z14.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2015')))
from BS Z14 where Z14.Belegdatum < CONVERT(Date,'01.01.2015')
UNION
Select distinct Z15.Artnr, Jahr = '2015',
P_Max = (Select MAX(Preis) From BS where Z15.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2016')),Q_Max = (Select TOP 1 Menge From BS where Preis = (Select MAX(Preis) From BS where Z15.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2016'))),
P_Min = (Select MIN(Preis) From BS where Z15.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2016')),Q_Min = (Select TOP 1 Menge From BS where Preis = (Select MIN(Preis) From BS where Z15.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2016')))
from BS Z15 where Z15.Belegdatum < CONVERT(Date,'01.01.2016')
UNION
Select distinct Z16.Artnr, Jahr = '2016',
P_Max = (Select MAX(Preis) From BS where Z16.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2017')),Q_Max = (Select TOP 1 Menge From BS where Preis = (Select MAX(Preis) From BS where Z16.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2017'))),
P_Min = (Select MIN(Preis) From BS where Z16.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2017')),Q_Min = (Select TOP 1 Menge From BS where Preis = (Select MIN(Preis) From BS where Z16.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2017')))
from BS Z16 where Z16.Belegdatum < CONVERT(Date,'01.01.2017')
UNION
Select distinct Z17.Artnr, Jahr = '2017',
P_Max = (Select MAX(Preis) From BS where Z17.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2018')),Q_Max = (Select TOP 1 Menge From BS where Preis = (Select MAX(Preis) From BS where Z17.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2018'))),
P_Min = (Select MIN(Preis) From BS where Z17.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2018')),Q_Min = (Select TOP 1 Menge From BS where Preis = (Select MIN(Preis) From BS where Z17.Artnr = Artnr AND Belegdatum < CONVERT(Date,'01.01.2018')))
from BS Z17 where Z17.Belegdatum < CONVERT(Date,'01.01.2018')
) AS Result order by Artnr,Jahr
Puuh, wäre sehr dankbar, wenn mir jemand eine bessere Lösung aufzeigen könnte.
Vielen Dank vorab!
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 368656
Url: https://administrator.de/forum/ms-sql-niedrigster-und-hoechster-datensatz-einer-gruppe-368656.html
Ausgedruckt am: 22.12.2024 um 03:12 Uhr
7 Kommentare
Neuester Kommentar
Moin,
Schaue dir mal die Funktion GROUP BY an.
Dann machst du zwei Subselects:
1. Select Jahr(Datum), Artikel min(Rabatt), min(preis) from yourTable group by Jahr(Datum), Artikel
2. Select Jahr(Datum), Artikel Max(Rabatt), max(preis) from yourTable group by Jahr(Datum), Artikel
Und am Ende ein inner Join mit Jahr und Artikel als schlüsselfelder...
Gruß
em-pie
Schaue dir mal die Funktion GROUP BY an.
Dann machst du zwei Subselects:
1. Select Jahr(Datum), Artikel min(Rabatt), min(preis) from yourTable group by Jahr(Datum), Artikel
2. Select Jahr(Datum), Artikel Max(Rabatt), max(preis) from yourTable group by Jahr(Datum), Artikel
Und am Ende ein inner Join mit Jahr und Artikel als schlüsselfelder...
Gruß
em-pie
Das geht auch in einem Select, ich bin nur nicht sicher ob der Rabatt ein absoluter Betrag ist oder prozentual aber man kann das ja alles erweitern:
SELECT ArtikelNr,
datepart(year,Belegdatum) AS Jahr,
min(Stückpreis * Menge) AS minPreis,
max(Stückpreis * Menge) AS maxPreis
FROM Artikel
GROUP BY ArtikelNr,datepart(year,Belegdatum)
Wenn du zusammenhängende Daten in mehreren Spalten brauchst gibt es mehrere Wege, z.B.:
Man beachte, das die ORDER BY-Konditionen von mehreren Datensätzen erfüllt werden können, dann wird ein zufälliger gewählt. Ansonsten kann man statt mit ROW_NUMBER() noch mit RANK() arbeiten und aus mehrere Datensätze im äußeren Select einen Durchschnitt errechnen.
SELECT t.*
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY ArtikelNr,datepart(year,Belegdatum) ORDER BY Stückpreis, Rabatt, Menge) AS zeile_min,
ROW_NUMBER() OVER (PARTITION BY ArtikelNr,datepart(year,Belegdatum) ORDER BY Stückpreis DESC, Rabatt DESC, Menge DESC) AS zeile_max,
ArtikelNr,
datepart(year,Belegdatum) AS Jahr,
Stückpreis,
Menge,
Rabatt
FROM Artikel
) t
WHERE zeile_min = 1
OR zeile_max = 1