# Select Distinct mit mehr als den Distinct Spalten



## BruderOli (26. August 2009)

Hallo zusammen,

nachdem ich das Internet durchforstet habe, und zur keinen Lösung gekommen bin, hier also meine Anfrage:

Ich habe eine Tabelle mit 5 Spalten
Spalte1, Spalte2, Spalte3, Spalte4, Spalte5

Was ich jetzt möchte ist:
Select distinct Spalte1, Spalte2, Spalte3
und von diesem Ergebnis will ich die ERSTE Information von Spalte 4 und 5 haben.

Zur Veranschaulichung hier ein Beispiel: 

Die Tabelle:
Spalte1         Spalte2          Spalte3            Spalte4           Spalte5
123456789  25.05.2005    1                       88                     2135
123456789  25.05.2005    1                       85                     7757
123456789  26.05.2005    1                       87                     7342
123456789  26.05.2005    1                       75                     7342
987654321  27.05.2005    2                       73                     4342
987654321  27.05.2005    2                       44                     4542
987654321  27.05.2005    3                       74                     4662

Das Ergebnis:
Spalte1         Spalte2          Spalte3            Spalte4           Spalte5
123456789  25.05.2005    1                       88                     2135
123456789  26.05.2005    1                       87                     7342
987654321  27.05.2005    2                       73                     4342
987654321  27.05.2005    3                       74                     4662

Sprich: Ein distinct auf den ersten 3 Spalten, wobei die Erste Information von Spalte 4 und 5 mitgenommen wird.

Umgangssprachlich (natürlich kein reales Beispiel, nur zum Verständnis) würd ich den SQL so aufbauen:
Select 
  distinct(Spalte1, Spalte2, Spalte3),
  FIRST(Spalte4 vom distinct),
  FIRST(Spalte5 vom distinct)

Ich hoffe ich hab es gut genug erklärt. Ich hoffe ihr könnt mir helfen.
Vielen Dank schonmal


----------



## zeja (26. August 2009)

Du musst Group By für die ersten 3 Spalten verwenden und für die anderen kannst du Min() verwenden.


----------



## BruderOli (26. August 2009)

Die Idee hatte ich auch schon, aber Min gibt mir dann ja den Minimalwert zurück. Ich will aber *nicht den Minimal*wert, sondern den *ersten Wert*.

Wenn du das dann mal eingeben würdest bei dir als SQL würde auch nicht das Ergebnis rauskommen, dass ich beschrieben habe.

Ich würde dann ja folgendes Ergebnis bekommen:
Spalte1 Spalte2 Spalte3 Spalte4 Spalte5
123456789 25.05.2005 1 85 2135
123456789 26.05.2005 1 75 7342
987654321 27.05.2005 2 44 4342
987654321 27.05.2005 3 74 4662

Aber das Ergebnis will ich ja nicht


----------



## Parantatatam (26. August 2009)

Ich würde mal sagen, dass da ein LIMIT 1 das Richtige für dich ist.


----------



## BruderOli (26. August 2009)

Naja Limit 1 klingt toll ... wie wäre das denn dann umzusetzen?

Bitte mal als SQL kurz schreiben mit den 5 Spalten, weil genau das ist ja mein Problem. Ich bekomme die richtige Syntax einfach net hin, sodass sie funktioniert.


----------



## Bernd1984 (26. August 2009)

Hallo BruderOli,

LIMIT 1 bringt dir nur etwas, wenn du nur eine Ergebniszeile haben möchtest. 
Aber das willst du ja nicht, denn du möchtest ja zu jeden gruppierten Wert (aus Spalte 1 bis 3) eine Zeile.

Also ist der Ansatz von zeja





> Du musst Group By für die ersten 3 Spalten verwenden und für die anderen kannst du Min() verwenden.


 der richtige Ansatz.

Das was dir hier fehlt ist die richtige Funktion für die Spalten 4 und 5.
Denn du möchtest wohl nicht den kleinsten Wert (Min()). Aber ein Kriterium für den jeweils zuletzt eingegebenen Datensatz gibt es nicht.
Zu lösen wäre dies Problem mit einem Feld (autoindex) in deiner Tabelle. Damit kannst du dann die Reihenfolge ermitteln.


----------



## BruderOli (26. August 2009)

Hab verstanden was du meinst. Allerdings ist es mir nicht möglich eine zusätzliche Spalte anzufertigen um dort den Autoindex einzutragen, ansonsten wäre das eine richtige Lösung.


----------



## kuddeldaddeldu (26. August 2009)

Hi,

ich fürchte, dann wirst Du Dein Vorhaben mit einem SQL-Statement nicht zuverlässig umsetzen können. Du brauchst ein Kriterium. Wie sonst wolltest Du z.B. den neuesten Datensatz ansich, ohne den ganzen Gruppierungskram auslesen?

LG


----------



## BruderOli (26. August 2009)

Tja, das ist hier die Frage ^^. Wie mach ich das...


----------



## kuddeldaddeldu (26. August 2009)

Eben drum. Ohne Sortierkriterium gar nicht.

LG


----------



## jeipack (26. August 2009)

Hi
was du willst ist

```
select Spalte1, Spalte2, Spalte3, first(Spalte4), first(Spalte5) from nowhere
group by Spalte1, Spalte2, Spalte3;
```
 Sprechen wir von MySQL? Dann geht es wirklich nicht. Andere Datenbanken können das zum Teil. Z.B. Access, weil es da immer eine Reihenfolge der Datensätze gibt.
Wenn es aber MySQL ist wirst du doch höchst wahrscheinlich schon einen AutoIndex haben?
Wenn du die Daten roh anschaust (also Select * from nowhere) wie findest du dann manuell raus welcher der erste Wert ist? Wenn du das raus finden kannst, kannst du es auch mit einer Abfrage, wenn du das nicht kannst ist die Information gar nicht vorhanden und es geht auch mit einer Abfrage nicht.


Gruss
jei


----------



## BruderOli (26. August 2009)

Des Rätsels Lösung:

1. Ich arbeite auf einer Oracle-Datenbank
2. Das Stichwort ist "Analytische Funktionen". Damit kann ich das umsetzen, was ihr wahrscheinlich mit dem "AutoIndex" meitntet.
Über jede Duplicate von S1, S2, S3 wird nun eine Nummer kreirt. Somit hat jetzt jeder meiner Datensätze eine Nummer. Der erste pro grp eine 1, der zweite eine 2, usw. Joa ... und jetzt kann ich natürlich am schluss abfragen Where BLA = 1.

Aber hier mal als SQL:

SELECT 
   Spalte1, 
   Spalte2, 
   Spalte3, 
   Spalte4, 
   Spalte5,  
FROM
(
SELECT 
   Spalte1, 
   Spalte2, 
   Spalte3, 
   Spalte4, 
   Spalte5,  
   RANK() OVER (PARTITION BY SPALTE1, SPALTE2, SPALTE3 ORDER BY SPALTE1 DESC) as MyRank
) HALLOWELT
WHERE
HALLOWELT.MyRank = 1


----------



## kuddeldaddeldu (26. August 2009)

Hi,



BruderOli hat gesagt.:


> 1. Ich arbeite auf einer Oracle-Datenbank



sei bitte so nett und nenne nächstes Mal das DBMS gleich, am besten im Titel, wie im oben angepinnten Thread gewünscht. Danke.



BruderOli hat gesagt.:


> 2. Das Stichwort ist "Analytische Funktionen". Damit kann ich das umsetzen, was ihr wahrscheinlich mit dem "AutoIndex" meitntet.



Aber auch da verwendest Du ein Sortierkriterium, nämlich SPALTE1. Und die ist doch pro Gruppe bzw. Partition gleich, wenn ich die Oracle-Abfrage richtig verstehe...

LG


----------



## jeipack (26. August 2009)

kuddeldaddeldu hat gesagt.:


> Aber auch da verwendest Du ein Sortierkriterium, nämlich SPALTE1. Und die ist doch pro Gruppe bzw. Partition gleich, wenn ich die Oracle-Abfrage richtig verstehe...


So wie ich das noch im Kopf habe (und ich arbeite zu wenig mir Oracle um sich darauf 100% verlassen zu können) arbeitet Oracle nicht nach dem FIFO-Prinzip (First In First Out) sondern sortiert die Daten automatisch nach der ersten Spalte (resp. nach dem Index falls einer vorhanden ist). Da die ersten 3 Spalten gleich sind wird also nach der vierten sortiert.

@BruderOli:
Da würde es mich nun interessieren ob es tatsächlich einen Unterschied zwischen deiner Abfrage und einer Abfrage ala

```
SELECT Spalte1, Spalte2, Spalte3, min(Spalte4), min(Spalte5)
```
gibt.

Ich kenne Rank nicht, aber wenn ich das richtig verstehe will er die Reihenfolge an den ersten 3 Spalten ausmachen, was ja nicht geht da die gleich sind.
Übrigens hätte ich so eine Rank Funktion ganz gerne für MySQL


----------



## kuddeldaddeldu (26. August 2009)

Hi,



jeipack hat gesagt.:


> So wie ich das noch im Kopf habe (und ich arbeite zu wenig mir Oracle um sich darauf 100% verlassen zu können) arbeitet Oracle nicht nach dem FIFO-Prinzip (First In First Out) sondern sortiert die Daten automatisch nach der ersten Spalte (resp. nach dem Index falls einer vorhanden ist). Da die ersten 3 Spalten gleich sind wird also nach der vierten sortiert.



Und das macht Oracle dann automatisch, wo er da doch explizit ein ORDER BY SPALTE1 drin hat?

LG


----------



## jeipack (27. August 2009)

Ich seh das so, dass das Order by gar nicht bringt, da Spalte1 ja immer gleich ist (Ist gruppiert und er will ja pro Gruppe eine Reihenfolge erstellen).


----------



## kuddeldaddeldu (27. August 2009)

Sag ich ja. 
Die Frage ist nur, ob Oracle die Datensätze in diesem Fall in einer wie auch immer definierten Reihenfolge liefert.

LG


----------



## BruderOli (28. August 2009)

Nur um euch mal kurz auf den laufenden zu halten. Es hat nicht funktioniert, ich dachte es nur zuerst ^^. Aber ich brauch nicht mehr lang, bis ich das Ergebnis hab. Ich werde dann mal posten, wie es dann wirklich funktioniert hat.


----------

