MS SQL Top2 von Jeder ID
Hallo zusammen
Ich habe eine Datenbank mit 2 Tabellen die wie folgt aussehen:
Tabelle tblShare
ID
Name
UNC
erfasst
Tabelle tblSize
ID
ShareID
datum
size
Das ganze ist Basis eines VBScripts das einmal in der Woche läuft und die Größe jeder Freigabe auf einem Fileserver erfasst.
In der Tabelle tblShare werden die Freigaben erfasst mit Freigabe Namen und dem UNC Pfad. In der Tabelle tblSize wird in der ShareID die ID der Freigabe aus tblShare eingetragen um das ganze dann mit einem INNER JOIN verbinden zu können.
Nun will ich eine Auswertung schreiben die aus der Tabelle die 2 letzen Wochen über das Datum mit der jeweiligen Größe ausliest um festzustellen welche Freigabe um wieviel gewachsen ist. Wenn ich die Max Funktion aufs Datum leg geht es für die letze Woche, aber ich bräuchte ja 2 Wochen um einen Vergleich zu haben. So stell ich mir die Ausgabe ca. vor:
Name | UNC | Datum_letzer_lauf | Size_letzer_lauf | Datum_vorletzer_lauf | Size_vorletzer_lauf | Veränderung_in_MB | Veränderung_in_%
Leider reicht hierfür meine SQL Kenntniss nicht mehr aus und auch Google hat mir nicht sonderlich weiter geholfen.
Vielen Dank
Mit freundlichen Grüßen
Phil
Ich habe eine Datenbank mit 2 Tabellen die wie folgt aussehen:
Tabelle tblShare
ID
Name
UNC
erfasst
Tabelle tblSize
ID
ShareID
datum
size
Das ganze ist Basis eines VBScripts das einmal in der Woche läuft und die Größe jeder Freigabe auf einem Fileserver erfasst.
In der Tabelle tblShare werden die Freigaben erfasst mit Freigabe Namen und dem UNC Pfad. In der Tabelle tblSize wird in der ShareID die ID der Freigabe aus tblShare eingetragen um das ganze dann mit einem INNER JOIN verbinden zu können.
Nun will ich eine Auswertung schreiben die aus der Tabelle die 2 letzen Wochen über das Datum mit der jeweiligen Größe ausliest um festzustellen welche Freigabe um wieviel gewachsen ist. Wenn ich die Max Funktion aufs Datum leg geht es für die letze Woche, aber ich bräuchte ja 2 Wochen um einen Vergleich zu haben. So stell ich mir die Ausgabe ca. vor:
Name | UNC | Datum_letzer_lauf | Size_letzer_lauf | Datum_vorletzer_lauf | Size_vorletzer_lauf | Veränderung_in_MB | Veränderung_in_%
Leider reicht hierfür meine SQL Kenntniss nicht mehr aus und auch Google hat mir nicht sonderlich weiter geholfen.
Vielen Dank
Mit freundlichen Grüßen
Phil
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 63193
Url: https://administrator.de/forum/ms-sql-top2-von-jeder-id-63193.html
Ausgedruckt am: 24.12.2024 um 02:12 Uhr
14 Kommentare
Neuester Kommentar
Also wenn Du es als eine SQL Abfrage haben willst, sieht das so aus (Wenn das Datum bei allen Shares gleich ist, also alle z.B. am 1.7.07 gesammelt werden und nächste Sammlung auch alle an einem anderen Tag z.B. 06.07.07):
Ist glaube ich etwas unverständlich, ich versuche es mal aufzudröseln:
Ich sortiere alle Daten absteigend, falls ein Wert mehrfach vorkommt nur einmal anzeigen (Distinct), nehme die 2 oberen Werte (Top 2) und dann davon das Minimum bzw. Maximum, damit habe ich die aktuelle und letzte Woche.
Ich joine die tblSize und tblShare über die ID und nehme nur die Datensätze, die über die Unterabfrage das Aktuelle Datum haben und mache das dann nochmals mit dem vorherigen Datum. Ergibt die 2 temporären Tabellen Aktuell und Letzte Woche.
Letztendlich joine ich dann die 2 temporären Tabellen über die ID und mache noch die 2 berechneten Felder.
Man könnte auch jede temporäre Tabelle als View anlegen und die verwenden, ist übersichtlicher, aber als eine ist auch machbar und eine Herausforderung.
SELECT Aktuell.Name, Aktuell.UNC, Aktuell.Datum, Aktuell.Size, LetzteWoche.Datum, LetzteWoche.Size, Aktuell.Size - LetzteWoche.Size AS Veraenderung, (( Aktuell.Size - LetzteWoche.Size) / LetzteWoche.Size)*100 AS Veraenderung_in_Prozent
from
(SELECT tblShare.ID, tblShare.UNC, tblShare.Name, tblSize.Datum, tblSize.Size
FROM tblShare, tblSize
WHERE tblShare.ID=tblSize.ShareID and (((tblSize.Datum)=(Select Max(Datum) from
(SELECT DISTINCT TOP 2 tblSize.Datum
FROM tblSize
ORDER BY tblSize.Datum DESC) as t1
)))) as Aktuell,
(SELECT tblShare.ID, tblShare.UNC, tblShare.Name, tblSize.Datum, tblSize.Size
FROM tblShare, tblSize
WHERE tblShare.ID=tblSize.ShareID and (((tblSize.Datum)=(Select Min(Datum) from
(SELECT DISTINCT TOP 2 tblSize.Datum
FROM tblSize
ORDER BY tblSize.Datum DESC) as t1
)))) as LetzteWoche
where Aktuell.ID=LetzteWoche.ID
Select Min(Datum) from
(SELECT DISTINCT TOP 2 tblSize.Datum
FROM tblSize
ORDER BY tblSize.Datum DESC) as t1
SELECT tblShare.ID, tblShare.UNC, tblShare.Name, tblSize.Datum, tblSize.Size
FROM tblShare, tblSize
WHERE tblShare.ID=tblSize.ShareID and (((tblSize.Datum)=(Select Max(Datum) from
(SELECT DISTINCT TOP 2 tblSize.Datum
FROM tblSize
ORDER BY tblSize.Datum DESC) as t1
)))) as Aktuell
Letztendlich joine ich dann die 2 temporären Tabellen über die ID und mache noch die 2 berechneten Felder.
Man könnte auch jede temporäre Tabelle als View anlegen und die verwenden, ist übersichtlicher, aber als eine ist auch machbar und eine Herausforderung.
Wenn ich die geänderte bei mir wieder einfüge, kommt Fehler in Join.
Seis drum, wir können das auch in Einzelschritten machen und es in 4 Views machen, da kann man dann bei jeder nachschauen, was rauskommt und eventuell den Fehler besser sehen.
Zuerst die View fürs Datum, habe ich admDatum genannt (ich schreibe immer nur den Select für die View hin):
Dann View admAktuell:
Dann View admLetzteWoche:
Dann die Ausgabe, admAusgabe:
Probiers also mal mit den Einzelschritten aus, dann sehen wir mal, wie weit wir kommen.
Seis drum, wir können das auch in Einzelschritten machen und es in 4 Views machen, da kann man dann bei jeder nachschauen, was rauskommt und eventuell den Fehler besser sehen.
Zuerst die View fürs Datum, habe ich admDatum genannt (ich schreibe immer nur den Select für die View hin):
SELECT DISTINCT TOP 2 tblSize.Datum
FROM tblSize
ORDER BY tblSize.Datum DESC;;
SELECT tblShare.ID, tblShare.Name, tblShare.UNC, tblSize.Datum, tblSize.Size
FROM tblSize, tblShare
WHERE (((tblSize.Datum)=(select max(datum) from admDatum)) AND ((tblSize.ShareID)=[tblShare].[ID]));;
SELECT tblShare.ID, tblShare.Name, tblShare.UNC, tblSize.Datum, tblSize.Size
FROM tblSize, tblShare
WHERE (((tblSize.Datum)=(select min(datum) from admDatum)) AND ((tblSize.ShareID)=[tblShare].[ID]));;
SELECT admAktuell.Name, admAktuell.UNC, admAktuell.Datum, admAktuell.Size, admLetzteWoche.Datum, admLetzteWoche.Size, admAktuell.Size - admLetzteWoche.Size AS Veraenderung, (( admAktuell.Size - admLetzteWoche.Size) / admLetzteWoche.Size)*100 AS Veraenderung_in_Prozent
FROM admAktuell, admLetzteWoche
WHERE admAktuell.ID = admLetzteWoche.ID;
Für die Veränderung in Prozent dividiere ich ja durch den Wert von letzter Woche.
Wenn der nun 0 ist, dann gibts ein Fehler.
Wenn Du nur die Veränderung in MB nimmst sollte es gehen.
Wie man jetzt aber in SQL dafür sorgt, daß bei 0 es keine Probleme gibt und trotzdem alles anzeigt wüsste ich nicht.
Mit einer Erweiterung der where Bedingung auf and admLetzteWoche.Size <> 0 könnte man natürlich die weglassen, die da Division by Zero erzeugen, aber dann fehlen halt ein paar Shares.
Je nachdem, wie genau es werden muß, könnte man natürlich auch 0,000001 oder so zu size addieren, daß es halt nur fast 0 ist.
Wenn der nun 0 ist, dann gibts ein Fehler.
Wenn Du nur die Veränderung in MB nimmst sollte es gehen.
Wie man jetzt aber in SQL dafür sorgt, daß bei 0 es keine Probleme gibt und trotzdem alles anzeigt wüsste ich nicht.
Mit einer Erweiterung der where Bedingung auf and admLetzteWoche.Size <> 0 könnte man natürlich die weglassen, die da Division by Zero erzeugen, aber dann fehlen halt ein paar Shares.
Je nachdem, wie genau es werden muß, könnte man natürlich auch 0,000001 oder so zu size addieren, daß es halt nur fast 0 ist.
Du verwendest einen MS SQL Server, oder?
Der hat die Eigenschaft, beim Rechnen mit Ganzzahlen immer auf Ganzzahlen zu runden und (dbo.admAktuell.size - dbo.admLetzteWoche.size) / dbo.admLetzteWoche.size wird daher auf 0 gerundet . Und dann hilft multiplizieren mit 100 nicht mehr.
Wenn die ganze Prozent reichen, dann auf ((dbo.admAktuell.size - dbo.admLetzteWoche.size) * 100) / dbo.admLetzteWoche.size ändern (also zuerst mit 100 multiplizieren, dann dividieren) oder eine Floating Point Operation erzwingen und
(cast(dbo.admAktuell.size - dbo.admLetzteWoche.size) as float) / dbo.admLetzteWoche.size * 100 nehmen.
Der hat die Eigenschaft, beim Rechnen mit Ganzzahlen immer auf Ganzzahlen zu runden und (dbo.admAktuell.size - dbo.admLetzteWoche.size) / dbo.admLetzteWoche.size wird daher auf 0 gerundet . Und dann hilft multiplizieren mit 100 nicht mehr.
Wenn die ganze Prozent reichen, dann auf ((dbo.admAktuell.size - dbo.admLetzteWoche.size) * 100) / dbo.admLetzteWoche.size ändern (also zuerst mit 100 multiplizieren, dann dividieren) oder eine Floating Point Operation erzwingen und
(cast(dbo.admAktuell.size - dbo.admLetzteWoche.size) as float) / dbo.admLetzteWoche.size * 100 nehmen.