SQL Grupieren und id zum einem minimum ermitteln

gaunt

Lt. Commander
Registriert
Aug. 2007
Beiträge
2.016
Hi
ich steh mal wieder auf dem Schlauch. Vielleicht kann mich mal einer runter schubsen.

Ich hab eine Tabelle und gruppiere in zwei Spalten. Jetzt brauche ich den PK der Zeile, welche in einer dritten Spalte den niedrigsten Wert hat.
Code:
select id from tabelle 
group by tabelle.integerWert1, tabelle.stringwert2
having min(tabelle.integerWert3)
Es werden über die Group Klausel zwar die richtigen Zeilen zusammen geführt, und frage ich nach dem select nach dem min und max Wert des dritten Wertes wird der auch korrekt ausgegeben.
Ich brauche aber die ID der Zeile welche den niedrigsten Betrag in Wert3 hat. In having scheint das min/max aber keine Funktion zu haben. Ich bekomme einfach irgendeine ID aus dem gruppierten Bereich.

Hätte hier vielleicht einer nen Tipp?
 
Kommt drauf an was du mit den Daten machen willst.
Am einfachsten wäre es nach integerWert3 zu sortieren.
Also :
select id, integerWert1, integerWert2, integerWert3 from table_name
group by id, integerWert1, integerWert2
order by integerWert3 asc
limit 1
Das ganze Gruppieren macht aber nur Sinn wenn du immer den gleichen integerWert3 pro Kombinationen aus integerWert1 und integerWert2 hast. Ansonsten gehen dir Informationen verloren (Das gleiche gilt für die id, die ich aus diesem Grund mit in die group by Klausel aufgenommen habe).

Eine andere mögliche Lösung wäre ein subselect in der where-Bedingung (where integerWert3=(select min(integerWert3) from ...)).
 
Zuletzt bearbeitet:
Funzt leider auch nicht:-(
Gebe ich z.B. zum testen einen der zu gruppierenden Werte in where vor und sortiere, dann gehts logischerweise. Aber ich habe diesen Wert leider nicht. Und sobald ich guppiere verliert order by seine bedeutung. Bzw. es greift eben erst, wenn die Abfrage mehere Ergebnisse liefert. Die würden dann sortiert.

Was geht:
Code:
SELECT GROUP_CONCAT(distinct id order by tabelle.integerWert3 asc  )
...
Nutze ich GroupConcat im Select bekomme ich alle ID's in richtiger reihenfolge aneinadergehängt. Aber dann müsste ich den String wieder auseinander nehmen. Nicht wirklich gut:-(

Wert 1 und 2 sind in der Gruppe immer gleich. Das ist auch richtig so und identifiziert eben jene Gruppe. Wert3 dagegen ist innerhalb der Gruppe aber natürlich unterschiedlich. ID sowieso. Ist halt der PK.
 
Ich denke, du willst den Subselect. Dann brauchst Du kein Group by oder having, es sei denn, du willst gruppieren.
Code:
select id from tabelle
[*]where tabelle.integerWert3 = (select min(tabelle.integerWert3) from tabelle)
 
Zuletzt bearbeitet:
Die große Frage ist:

Willst du die ID der Zeile mit dem Minimalwert pro Gruppierung oder für die gesamte Tabelle?

Also angenommen du hast folgende Tabelle:

Code:
id | i1 | i2 | i3
-----------------
1  | 1  | 1  | 9
2  | 1  | 1  | 8
3  | 2  | 2  | 4

Willst du nach dem Query (mit GROUP BY auf i1 und i2) als Ergebnis das:
id = 1 , i3 = 9 UND id = 3 , i3 = 4
oder das:
id = 1 , i3 = 9
?
 
So, Ostern is vorbei:-(
Erstmal sorry dass ich das Orginalmodell nicht posten kann, aber ist eben keine private DB.

Willst du die ID der Zeile mit dem Minimalwert pro Gruppierung oder für die gesamte Tabelle?
Für die Gruppe natürlich. Für die ganze Tabelle wäre es ja trivial.
Die ID, also der PrimaryKey, wird benötigt um in der selben Tabelle für spätere performancerelevante Abfragen eine Zeile zu markieren.

Gelöst hab ichs mittlerweile. Allerdings mit einem Zwischenschritt in einem ETL Tool.
Ich nutze GroupConcat wie oben beschrieben. Den String zerlege ich mit instr und substring. Vorher wird mit if geprüft ob der seperator aus dem GroupConcat vorkommt. So habe ich die korrekten ID's und kann die Zeile updaten.

Aber das muss doch irgendwie direkt in SQL gehen... Würde mich einfach interessieren.
So sieht das select im moment als Pseudocode aus:
Code:
select 
IF(
	position des GroupConcat Seperators >0
	,wenn ja dann nimm aus dem concatinierten String den Anfang bis zum ersten Seperator
	,wenn nein dann den gesamten Concatinieren String. Denn dann enthält er nur eine ID
)
from tabelle 
group by tabelle.Wert1, tabelle.Wert2
Das ist nicht schön, liefert aber den gewünschten Wert.

Jetzt will ich den update machen. Geht nicht, warum?
http://dev.mysql.com/doc/refman/5.6/en/update.html
Currently, you cannot update a table and select from the same table in a subquery.
Klar oder? Im Update muss ich ein subselect verwenden und das geht nicht.
Also ginge es nur über manuell oder implzit erstellte Temp Tables :rolleyes:

Hm, das muss doch irgendwie eleganter gehen:-(
 
Code:
select distinct(ID) from table_name A
where IntegerWert3=(select min(B.IntegerWert3) from table_name B where A.IntegerWert1=B.IntergerWert1 and A.IntegerWert2=B.IntegerWert2);


Das ist so ähnlich wie von miac nur mit ~simuliertem group by. Als Ergebnis solltest du alle IDs bekommen, die innerhalb ihrer Gruppe (IntegerWert1, IntegerWert2) den geringsten Wert für IntegerWert3 besitzen. Die Abfrage kann bei nicht gesetzten Indizes und großen Datenmengen auf Grund der Unterabfrage eine lange Laufzeit haben. Die Ergebnisliste der Abfrage kann in einer temporären Tabelle gespeichert werden, anschließend als Referenz für das Update dienen und danach gelöscht werden.
 
Zurück
Oben