Seite 1 von 3

Group by [ERLEDIGT]

Verfasst: So, 28. Feb 2021 8:22
von Manfred
irgendwie komme ich nicht weiter
ich möchte hierzu

Code: Alles auswählen

SELECT li.id AS IdLInie,
                      li.bez AS Linie,
                      li.idageber,
                      fa.id AS IDFahrt,
                      fa.idlinie AS IDLINIE_ausFahrt,
                      li.nummer AS NrLinie,
                      ag.bezkurz AGKurz,
                      fa.datumab,
                      fa.uhrzeitab
               FROM linien li
               LEFT JOIN fahrten fa ON fa.idlinie = li.id
               LEFT JOIN auftraggeber ag ON ag.id=li.idageber
               ORDER BY li.nummer, fa.datumab, fa.uhrzeitab
eine Gruppierung auf die li.id machen. Wie wird sowas gemacht? Group by bekomme ich nicht hin. Irgendwas mache ich da wohl falsch

Re: Group by

Verfasst: So, 28. Feb 2021 11:49
von nightcrawler
bei einem GROUP BY müssen alle Spalten, welche nicht aggregiert sind (zB über MIN, MAX, AVG, ...) in die GROUP BY Klausel aufgenommen werden.
Zeig doch bitte mal an einem Beispiel, wie die Datensätze aussehen und wie die gewünschten Ergebnis-Datensätze aussehen sollen.

Re: Group by

Verfasst: So, 28. Feb 2021 13:23
von Manfred
Problem erkannt, Problem gebannt.
Jetzt verstehe ich was Du meinst. Das hier klappt.

Code: Alles auswählen

SELECT li.id, 
       li.bez,
       max(fa.datumab) AS datum,
Count(li.id) Fahrten 
FROM linien li
LEFT JOIN fahrten fa ON fa.idlinie=li.id
GROUP BY li.id, li.bez, fa.datumab

Re: Group by [ERLEDIGT]

Verfasst: So, 28. Feb 2021 18:25
von Marcus Herz
Ich hab deine Tabellen nicht, aber es müsste doch schon

Code: Alles auswählen

SELECT li.id, 
       li.bez,
       max(fa.datumab) AS datum,
Count(li.id) Fahrten 
FROM linien li
LEFT JOIN fahrten fa ON fa.idlinie=li.id
GROUP BY li.id, li.bez
funktionieren?

Re: Group by [ERLEDIGT]

Verfasst: So, 28. Feb 2021 19:18
von Manfred
ich brauche auf jeden Fall noch die weitere Spalte, weil da Werte stehen können, mit denen ich weiter arbeiten muß.

Re: Group by [ERLEDIGT]

Verfasst: Mo, 01. Mär 2021 9:11
von Manfred
merkwürdig, jetzt klappt es genau so:

Code: Alles auswählen

SELECT li.id, 
       li.bez,
	   li.nummer,
	   fa.datumab,
Count(li.id) Fahrten 
FROM linien li
LEFT JOIN fahrten fa ON fa.idlinie=li.id
GROUP BY li.id, li.bez, li.nummer, fa.datumab
Ich vermute aber, es hat jetzt KLick gemacht. Wenn ich nur die Spalten angebe, dann müssen die in group by rein, wenn ich die aber z.B. zusammenrechne, oder min max usw. mache, dann müssen die nicht mit rein!?

Re: Group by [ERLEDIGT]

Verfasst: Mo, 01. Mär 2021 9:48
von nightcrawler
richtig ;)
Du kannst aber alternativ beim GROUP BY auch die Spaltennummer angeben:

Code: Alles auswählen

SELECT li.id, 
  li.bez,
  li.nummer,
  fa.datumab,
  Count(li.id) Fahrten 
FROM linien li
LEFT JOIN fahrten fa ON fa.idlinie=li.id
GROUP BY 1,2,3

Re: Group by [ERLEDIGT]

Verfasst: Mo, 01. Mär 2021 9:53
von Manfred
die Logik erschließt sich mir aber nicht. Ich möchte doch einfach nur eine Zusammenfassung einer Spalte. Das da dann evtl. ein Sort drauf müßte, wäre nachvollziehbar. Aber warum müssen alle Spalten mit in Group by? Das kann doch ein richtig heftiger Aufwand werden, wenn ich eine größere Anzahl Spalten anzeigen will/muß.

Re: Group by [ERLEDIGT]

Verfasst: Mo, 01. Mär 2021 14:07
von nightcrawler
irgendwoher muss das DBMS doch wissen, wie Du Deine Abfrage aufbaust. Der SQL Standard sieht hier eben das GROUP BY für alle nicht aggregierten Spalten vor. Es gibt manche DBMS, die nichtkonform mit dem Standard das GROUP BY automatisch erstellen. Der ADS gehört aber nicht dazu;)

Re: Group by [ERLEDIGT]

Verfasst: Sa, 20. Nov 2021 17:28
von Manfred
ich komme voran, aber nur sehr schwerlich.
Hier nochmal ein weiteres Problem:
das klappt,

Code: Alles auswählen

SELECT fz.kfznr, 
	   max(fz.tachostand) as tachostand,
	   max(tb.tankdatum) tankdatum,
	   hs.bez AS hersteller, 
	   fz.datumez, 
	   fza.bez AS Fahrzeugart
FROM fahrzeuge fz
LEFT JOIN hersteller hs ON hs.id=fz.idherstell
LEFT JOIN fahrzeugarten fza ON fza.id=idaufbau
LEFT JOIN tankbuch tb ON tb.kfznr=fz.kfznr
WHERE fz.aktiv = true
GROUP BY fz.kfznr, hersteller, fz.datumez, fahrzeugart
ORDER BY fz.kfznr
aber eigentlich müßte ich es so haben.
Die Spalte tb.menge muß angezeigt werden.

Code: Alles auswählen

SELECT fz.kfznr, 
	   max(fz.tachostand) as tachostand,
	   max(tb.tankdatum) tankdatum,
	   tb.menge,
	   hs.bez AS hersteller, 
	   fz.datumez, 
	   fza.bez AS Fahrzeugart
FROM fahrzeuge fz
LEFT JOIN hersteller hs ON hs.id=fz.idherstell
LEFT JOIN fahrzeugarten fza ON fza.id=idaufbau
LEFT JOIN tankbuch tb ON tb.kfznr=fz.kfznr
WHERE fz.aktiv = true
GROUP BY fz.kfznr, hersteller, fz.datumez, fahrzeugart
ORDER BY fz.kfznr
Aber das scheitert.

EDIT:
Es ist ja so, das bei "Group by" folgendes passiert. In meinem Fall sind die Inhalte aus dem Fahrzeug fz. Die sind ja bei jeder KfzNr gleich also werden die in Group by eingetragen. So weit habe ich das verstanden. Jetzt werden alle kfznr zusammengefaßt. Dann werden die Zeilen, die zu jeder kfznr passen mit max() (tachostand, tankdatum) ermittelt und die maximalen Werte aus jeder Spalte werden dann in eine neue Zeile geschrieben, die das Ergbnis darstellt. Was als Folge hat, das die ermittelten Ergebnisse nicht aus einer Zeilen stammen, sondern aus verschiedenen Zeilen kommen können. (Das habe ich bis gerade nicht erkannt) Wenn ich jetzt also die tb.menge haben möchte muß ich natürlich dem Server klarmachen welche ich möchte. Ich möchte jeweils die Menge haben aus der Zeile, in der auch das jüngste Tankdatum steht. Im besten Fall also aus dem letzten Eintrag zu der Gruppe, oder je nach Sortierung aus dem ersten Eintrag der Gruppe. Aber wie mache ich das dem SQl Server klar?

Es müßte dann eigentlich so aussehen:

Code: Alles auswählen

SELECT fz.kfznr, 
	   fz.tachostand,
	   max(tb.tankdatum) tankdatum,
	   tb.menge,
	   hs.bez AS hersteller, 
	   fz.datumez, 
	   fza.bez AS Fahrzeugart
FROM fahrzeuge fz
LEFT JOIN hersteller hs ON hs.id=fz.idherstell
LEFT JOIN fahrzeugarten fza ON fza.id=idaufbau
LEFT JOIN tankbuch tb ON tb.kfznr=fz.kfznr
WHERE fz.aktiv = true
GROUP BY fz.kfznr, hersteller, fz.datumez, fahrzeugart
ORDER BY fz.kfznr
gibt aber dann Probleme, weil der Server ja gar nicht weiß, welchen Wert er da nehmen sol für die Spalten, die nicht in Group By stehen.
Kann man da was mit HAVING machen?

Re: Group by [ERLEDIGT]

Verfasst: Sa, 20. Nov 2021 21:13
von Manfred
Oder evtl noch ganz anders. Wie würde ein sql Befehl aussehen, der nach dem tankdatum sortiert und zwar so, das das letzte am anfang steht und wird einfach nur 1 Satz genommen. Das sollte dann passen. Oder so ähnlich

Re: Group by [ERLEDIGT]

Verfasst: Sa, 20. Nov 2021 21:26
von Marcus Herz
Was jetzt, erledigt oder neue Frage

Re: Group by [ERLEDIGT]

Verfasst: Sa, 20. Nov 2021 23:58
von Werner_Bayern
Manfred hat geschrieben: Sa, 20. Nov 2021 21:13 Oder evtl noch ganz anders. Wie würde ein sql Befehl aussehen, der nach dem tankdatum sortiert und zwar so, das das letzte am anfang steht und wird einfach nur 1 Satz genommen. Das sollte dann passen. Oder so ähnlich

Code: Alles auswählen

select _deine_Felder_ from _deine_Tabelle_ where _dein_Filter_ order by tankdatum desc Limit 1
oder

Code: Alles auswählen

select max(tankdatum) from _deine_Tabelle_ where _dein_Filter_

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 9:55
von Manfred
@Werner,
sorry, aber damit komme ich nicht weiter. Ich muß nach kfznr sortiert haben und außerdem klappt das LIMIT 1 beim ADS wohl nicht. Das mit der kfznr könnt ich über einen Zwischenschritt lösen, indem ich zuerst in ein DataoBject schreibe und dann sortiere (ist zwar nicht im Sinne des Erfinders, aber als vorläufige Notlösung ginge das). Wie müßte LIMIT 1 beim ADS gemacht werden?

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 13:08
von Marcus Herz
Ich schau mir das am fienstag mal. Aber select top 1 start at x fieldlist ... zuverlässig bei ads

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 15:10
von Werner_Bayern
Servus Manfred,

lt. ADS Hilfe:
Limiting Query Results

Code: Alles auswählen

SELECT TOP 1 * FROM emp

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 15:31
von Manfred
Hi Werner,
das hier habe ich gemacht. (vielleicht ist es ja falsch, es kann ja sein)

Code: Alles auswählen

SELECT TOP 1 fz.kfznr, 
       fz.tachostand,
       tb.tankdatum,
       tb.kmstand,
	   tb.menge,
       hs.bez AS hersteller, 
       fz.datumez, 
       fza.bez AS Fahrzeugart
FROM fahrzeuge fz
LEFT JOIN hersteller hs ON hs.id=fz.idherstell
LEFT JOIN fahrzeugarten fza ON fza.id=idaufbau
LEFT JOIN tankbuch tb ON tb.kfznr=fz.kfznr
WHERE fz.aktiv = true
ORDER by tb.tankdatum DESC
Dann kommt nur 1 Satz. Und das ist eindeutig zu wenig.

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 16:46
von Werner_Bayern
Manfred hat geschrieben: So, 21. Nov 2021 15:31 Hi Werner,
das hier habe ich gemacht. (vielleicht ist es ja falsch, es kann ja sein)

Code: Alles auswählen

SELECT TOP 1 fz.kfznr, 
Dann kommt nur 1 Satz. Und das ist eindeutig zu wenig.
:D Der war gut!

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 16:51
von Manfred
ja sicher, aber welche Zahl sollte da rein? Kläre mich auf

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 16:57
von Manfred
vielleicht ist die Frage von mir auch nicht richtig rübergekommen.
Es gibt eine Menge an Fahrzeugen. Die möchte ich komplett aufgelistet haben. Aber zu jedem Fahrzeug gibt es eine weitere unendliche Menge an Einträgen im Tankbuch. Aus dem brauche ich aber nur de Eintrag mit dem höchsten DAtum. Wenn der gefunden wurde, dann muß ich dazu auch die Menge haben, die getankt wurde. Es würde auch genügen, wenn ich zu jedem Tankvorgang eines Fahrzeugs den ich finde immer nur den ersten nehme. Der steht dann sowieso am Anfang, weild er Index so gesetzt ist. Das klang mit TOP 1 für mich so, als wenn es klappen würde.

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 17:49
von Werner_Bayern
Servus Manfred,

das war ja auch "nur" meine Antwort auf Deine Frage:
Wie müßte LIMIT 1 beim ADS gemacht werden?
Ich bin jetzt nicht der SQL-Experte, arbeite per SQL nur mit dem PostgreSQL, aber Du musst halt bei Deinem Join das entsprechend berücksichtigen und nicht bei Deiner Hauptabfrage.

Also entweder ein select aus einem select mit top 1 oder geht's evtl. beim ADS auch in Verbindung mit Left join. Steht in der Hilfe zu join nichts entsprechendes? Ansonsten probieren oder auf einen SQL-ADS-Experten hier warten 8)

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 18:45
von Marcus Herz
den ich finde immer nur den ersten nehme. Der steht dann sowieso am Anfang, weild er Index so gesetzt ist.
Diese Denke gibts bei SQL nicht mehr

Zu deinem Problem:
Du musst ein LEFT JOIN auf die Tabelle mit dem letzten Tankeintrag machen:

Code: Alles auswählen

SELECT TOP 1 fz.kfznr, 
       fz.tachostand,
       tb.tankdatum,
       tb.kmstand,
	tb.menge,
       hs.bez AS hersteller, 
       fz.datumez, 
       fza.bez AS Fahrzeugart
FROM FAHRZEUG fz
LEFT JOIN (select * from TANKBUCH where rowid in (
	select tankbuch.rowid
	from tankbuch
	inner join tankbuch tb on tankbuch.kfznr = tb.kfznr 
	and tb.datum > tankbuch.datum)) tb on tb.kfznr = fz.kfznr

Hab leider dein Tabelle nicht zum Testen

Re: Group by [ERLEDIGT]

Verfasst: So, 21. Nov 2021 18:59
von Marcus Herz
Bei grossen datenmengen kann es sein, dass der inner join sehr langsam ist. Ich wüsste noch ein andere Lösung die wir dann testen können zwecks Performance

Re: Group by [ERLEDIGT]

Verfasst: Mo, 29. Nov 2021 11:41
von Manfred
Hallo Markus,
das hier zeigt zumindest an, das es läuft. Es sieht aber so aus, als wenn es nahezu unendlich lange läuft, was für den Livebetrieb nicht gut ist als Response

Code: Alles auswählen

SELECT TOP 1 fz.kfznr, 
       fz.tachostand,
       tb.tankdatum,
       tb.kmstand,
	tb.menge,
       hs.bez AS hersteller, 
       fz.datumez, 
       fza.bez AS Fahrzeugart
FROM FAHRZEUGe fz
LEFT JOIN hersteller hs ON hs.id=fz.idherstell
LEFT JOIN fahrzeugarten fza ON fza.id=idaufbau
LEFT JOIN (select * from TANKBUCH where rowid in (
	select tankbuch.rowid
	from tankbuch
	inner join tankbuch tb on tankbuch.kfznr = tb.kfznr 
	and tb.tankdatum > tankbuch.tankdatum)) tb on tb.kfznr = fz.kfznr

Re: Group by [ERLEDIGT]

Verfasst: Mo, 29. Nov 2021 11:47
von nightcrawler
Manfred,
kannst Du bitte ein kleines Beispiel mit den benötigten Daten und der gewünschten Ergebnismenge zusammenstellen, so dass ein SQL eindeutig verifiziert werden kann? Am besten als SQL-Script (create table .... insert into ...).
So wie ich es sehe, brauchst Du aus den Aggregaten nur die getankte Menge - die bekommt man einfacher - und den jeweils letzten Tankvorgang. Das wird dann erst mit dem Rest der Fahrzeugdaten verknüpft.

Edit: Deine Anforderungen sehen aus wie ein Haus, bei welchem vom Bauherrn nach Fertigstellung noch der Wunsch nach einem Keller kommt.