Sql Abfrage mit Gruppierung
Localhorst
- datenbank
0 Klaus Mock0 Localhorst0 Localhorst
0 Frank (no reg)0 Ilja0 Klaus Mock0 Ilja0 Klaus Mock0 Ilja
Hallo Forum,
ich habe eine Tabelle die wie folgt aufgebaut ist.
schnittnummer int(10) (Zahl von 0 - ca 10000,Pri. Key)
gruppe int(10)
status tynint(1)
user_id int(10)
datum int(20)
1996;0;0;0;; Block 1
2011;1;2;1;1168870968; Block 2 (gleiche Gruppennr.)
2026;1;2;1;1168870968;
2041;1;2;1;1168870968;
2056;1;2;1;1168870968;
2071;0;2;1;1168871122; Block 3
2086;0;2;1;1168870968;
2101;0;2;1;1168870968;
2116;0;0;1;1168870434;
2131;2;2;1;1168871029; Block 4 (gleiche Gruppennr.)
2146;2;2;1;1168871029;
2161;2;2;1;1168871029;
2176;2;2;1;1168871029;
Die Zeilen des zweiten und des letzten Blocks haben jeweils die selbe Gruppe.
Frage:
Ist es möglich, in einer SQL Abfrage von den Blocks, die jeweils die selbe Gruppennummer haben die kleinste und größte Schnittnummer zu bekommen. Wenn die Gruppennummer 0 ist soll direkt die Schnittnummer raus kommen.
Das Ergebnis sollte also wie folgt aussehen
1996; (Erster Block, Gruppe 0 also normal ausgeben)
2011; (Min Schnittnummer von zweitem Block, Gruppe 1)
2056; (Max Schnittnummer von zweitem Block, Gruppe 1)
2071;
2086;
2101;
2116;
2131; (Min Schnittnummer von viertem Block, Gruppe 2)
2176; (Max Schnittnummer von viertem Block, Gruppe 2)
Ich denke, dass es evtl. mit dem group Befehl irgentwie gehen könnte, aber leider schaue ich schon zu lange drauf um noch eine Chance zu haben eine Lösung zu finden. Für etwas Hilfe wäre ich sehr dankbar.
Mit freundlichen Grüßen
Localhorst
Hallo,
Frage:
Ist es möglich, in einer SQL Abfrage von den Blocks, die jeweils die selbe Gruppennummer haben die kleinste und größte Schnittnummer zu bekommen. Wenn die Gruppennummer 0 ist soll direkt die Schnittnummer raus kommen.
D.h. also, dass es eine unterschiedliche Behandlung für Datensätze mit Gruppennummer 0 und solech mit einer anderen Gruppennummer gibt.
Erstere, so verstehe ich das zumindest, sollen ohne Gruppierung behandelt werden, zweitere jedoch mit einer Gruppierung unter Einbeziehung von Aggregat-Funktionen:
SELECT x FROM
(
SELECT x FROM tabelle
WHERE y = 0
UNION
SELECT MIN(x) FROM tabelle
WHERE y >0
UNION
SELECT MAX(x) FROM tabelle
WHERE y >0
)
ORDER BY x ASC
Das wäre eine mögliche Variante unter der Voraussetzung, dass die Datenbank diese Syntax versteht. Da Du nicht angegeben hast, welche Datenbank und vroi allem welche Version dieser Datenbank Du verwendest, gehe ich einmal davon aus, dass dem so ist.
Grüße
Klaus
Hallo und Danke für deine Antwort, ich versuche gerade diese um zu setzen.
D.h. also, dass es eine unterschiedliche Behandlung für Datensätze mit Gruppennummer 0 und solech mit einer anderen Gruppennummer gibt.
Erstere, so verstehe ich das zumindest, sollen ohne Gruppierung behandelt werden, zweitere jedoch mit einer Gruppierung unter Einbeziehung von Aggregat-Funktionen:
.....
Das wäre eine mögliche Variante unter der Voraussetzung, dass die Datenbank diese Syntax versteht. Da Du nicht angegeben hast, welche Datenbank und vroi allem welche Version dieser Datenbank Du verwendest, gehe ich einmal davon aus, dass dem so ist.
Ich benutze eine lokale MySQL Datenbank der Version 5.0.24a
Gruß
Localhorst
SELECT x FROM
(
SELECT x FROM tabelle
WHERE y = 0
UNION
SELECT MIN(x) FROM tabelle
WHERE y >0
UNION
SELECT MAX(x) FROM tabelle
WHERE y >0
)
ORDER BY x ASC
Habe deine Abfrage Umgebaut und es kommt leider ein Fehler.
Folgende Ausgabe bekomme ich von PHPmyAdmin
Fehler
SQL-Befehl: Dokumentation
SELECT schnittnummer
FROM 16_96(
SELECT schnittnummer
FROM 16_96
WHERE gruppe =0
UNION
SELECT MIN( schnittnummer )
FROM 16_96
WHERE gruppe >0
UNION
SELECT MAX( schnittnummer )
FROM 16_96
WHERE gruppe >0
)
ORDER BY schnittnummer ASC
MySQL meldet: Dokumentation
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(
SELECT schnittnummer FROM 16_96
WHERE gruppe = 0
UNION
SELECT MIN(schnitt' at line 2
Hallo,
SELECT x FROM
(
[...]
)
ORDER BY x ASC
versus
SELECT schnittnummer
FROM 16_96(
[...]
)
ORDER BY schnittnummer ASC
Was ist, ausser den Bezeichnungen und Zeilenumbrüchen anders?
Tip: es hat was mit 16_96 zu tun;-)
Grüße
Klaus
Hoi,
ich würde mal vorschlagen:
Baue drei einzelne Abfragen, in denen du deine Ergebnismenge genau
beschreibst mithilfe von MAX(..) bzw. MIN(..), GROUP BY und WHERE
und füge sie mittels UNION aneinander.
Ciao, Frank
yo,
schnittnummer int(10) (Zahl von 0 - ca 10000,Pri. Key)
das ist nicht ideal, einen sogenannten sprechenden schlüssel als primary key zu benutzen. wenn es keine gründe dafür gibt, zum beispiel vorgabe des kunden, dann nimm lieber einen künstlichen schlüssel und mach für die schnittnummer eine extra spalte, die unique und not null contraints besitzt.
Die Zeilen des zweiten und des letzten Blocks haben jeweils die selbe Gruppe.
das kann ich nicht erkennen, ist nicht der zweite wert in den beispieldaten die gruppenzuordnung oder irre ich mich da ?
Ist es möglich, in einer SQL Abfrage von den Blocks, die jeweils die selbe Gruppennummer haben die kleinste und größte Schnittnummer zu bekommen. Wenn die Gruppennummer 0 ist soll direkt die Schnittnummer raus kommen.
ja, das ist nicht besonders schwer, ich würde keinen union wie bereits vorgeschlagen benutzen, da du damit keine felxibilität erreichst, wenn mehr gruppen dazu kommen.
besser sind "korrelierenden unterabfragen", in der die ganze magic steckt:
SELECT DISTINCT tab1.hier_spalten_zur_ausgabe_angeben
FROM tablle tab1
WHERE tab1.schnitternummer = (SELECT MAX(tab2.schnittnummer) FROM tabelle tab2 WHERE tab1.gruppe = tab2.gruppe)
OR tab1.schnitternummer = (SELECT MIN(tab3.schnittnummer) FROM tabelle tab3 WHERE tab1.gruppe = tab3.gruppe)
Ilja
Hallo,
das ist nicht ideal, einen sogenannten sprechenden schlüssel als primary key zu benutzen. wenn es keine gründe dafür gibt, zum beispiel vorgabe des kunden, dann nimm lieber einen künstlichen schlüssel und mach für die schnittnummer eine extra spalte, die unique und not null contraints besitzt.
Ich habe bis jetzt noch nie verstanden, warum man in einer Tabelle, in der eine Spalte existiert, die einen Datensatz bereits eindeutig identifiziert (was ja die Aufgabe eines Primär-Schlüssels sein soll), noch zusätzlich eine zweite Spalte anlegen soll, deren Wert dann, so vermute ich mal, per Sequenz oder AutoID oder wie auch immer erzeugt wird.
Hat das nur mit "Das macht man halt so" zu tun, oder gibt es einen triftigen Grund dafür.
Ich sehe nämlich in der Verwendung von mehreren Unique Keys, wobei jeder davon nur eine jeweils eine Spaltge betrifft, eher nachteilig, weil mehr Verwaltungsaufwand.
SELECT DISTINCT tab1.hier_spalten_zur_ausgabe_angeben
FROM tablle tab1
WHERE tab1.schnitternummer = (SELECT MAX(tab2.schnittnummer) FROM tabelle tab2 WHERE tab1.gruppe = tab2.gruppe)
OR tab1.schnitternummer = (SELECT MIN(tab3.schnittnummer) FROM tabelle tab3 WHERE tab1.gruppe = tab3.gruppe)
Naja, aber eigentlich wollte der OP MIN und MAX nur von den Gruppen > 0 haben, während für die Gruppe == 0 alle Werte ausgegeben werden sollten.
Abgesehen davon finde ich, dass das UNION-Statement leichter zu lesen ist, abgesehen von allfälligen Performance-Aspekten, die ich so einfach aus der Hüfte aber nicht beantworten könnte.
Grüße
Klaus
yo,
Ich habe bis jetzt noch nie verstanden, warum man in einer Tabelle, in der eine Spalte existiert, die einen Datensatz bereits eindeutig identifiziert (was ja die Aufgabe eines Primär-Schlüssels sein soll), noch zusätzlich eine zweite Spalte anlegen soll, deren Wert dann, so vermute ich mal, per Sequenz oder AutoID oder wie auch immer erzeugt wird.
ja hat es, wobei es nicht darum geht, mehr als einen unique und nicht zu vergessen not null spalte zu haben, sondern darum, keine "inhalte" in den pk zu legen. das problem dabei ist, dass sich die inhalte im laufe der zeit ändern können und man dann nicht nur den sprechenden schlüssel ändern muss, sondern aller wahrschenilichkeit auch alle anderen spalten, wo er als fremdschlüssel verwendet wird.
ein beispiel dafür wäre eine autonummer. diese ist sicherlich unique und not null, erfüllt also beide kritereien eines pk. aber sie kann sich für eine und dasselbe auto im laufe der zeit ändern. und das wäre schlecht, wohingegen eine künstliche spalte keine probleme damit hätte.
abgesehen von allfälligen Performance-Aspekten, die ich so einfach aus der Hüfte aber nicht beantworten könnte.
die performance von unterabfragen hat einen schlechten ruf. in der praxis sind sie aber in regel viel schneller, besonders im vergleich zu UNION, der meiner meinung nach in diesem fall nicht nur unflexibler ist, sondern auch eine sortierung der gesamten ergebnismenge nach sich zieht, da er distincte werte auschließt, mal davon abgesehen, ob das überhaupt gewollt ist.
Ilja
Hallo,
ja hat es, wobei es nicht darum geht, mehr als einen unique und nicht zu vergessen not null spalte zu haben, sondern darum, keine "inhalte" in den pk zu legen. das problem dabei ist, dass sich die inhalte im laufe der zeit ändern können und man dann nicht nur den sprechenden schlüssel ändern muss, sondern aller wahrschenilichkeit auch alle anderen spalten, wo er als fremdschlüssel verwendet wird.
Dann heisst das ja wohl, dass eine der Eigenschaften eines Primärschlüssels dessen unveränderlichkeit über die gesamte Lebensdauer eiens Datensatzes ist. Wenn das garantiert wäre, würde auch nichts dagegen sprechen, dass, wie Du es nennst, Inhalte im PK hinterlegt sind.
ein beispiel dafür wäre eine autonummer. diese ist sicherlich unique und not null, erfüllt also beide kritereien eines pk. aber sie kann sich für eine und dasselbe auto im laufe der zeit ändern.
Naja, eine Fahrgestellnummer ist ebenfalls eindeutig und nicht veränderbar (ausser kriminelle Elemente sind am Werk, aber da frage ich mich, ob die dann eine Datenbank einsetzen;-). Also würde ich eher die hernehmen.
Wie oben gesagt, denke ich auch, dass der PK während der Lebenszeit nicht veränderlich sein soll. _Wie_ der Wert jedoch generiert wird, und ob er so 'nebenbei' auch noch eine Bedeutung hat, ist imho unerheblich. Diese Eigenschaft hatten allerdings Identifikationsnummern auch schon in de Pre-IT-Ära.
die performance von unterabfragen hat einen schlechten ruf. in der praxis sind sie aber in regel viel schneller, besonders im vergleich zu UNION, der meiner meinung nach in diesem fall nicht nur unflexibler ist, sondern auch eine sortierung der gesamten ergebnismenge nach sich zieht, da er distincte werte auschließt, mal davon abgesehen, ob das überhaupt gewollt ist.
Naja, UNION macht in der Regel ein implizites DISTINCT, welches man mit UNION ALL dann meist auch verhindern kann.
Und, wie schon gesagt, ich könnte das rein aufgrund des Statements nicht wirklich entscheiden, was schneller sein würde.
Ausserdem, was meinst Du mit unflexibler? Das kann ich auch nicht sehen. Ich bin der Meinung, dass es irgendwann einen Punkt gibt, wo man für eine bestimmte Aufgabe ein bestimmtes Staement braucht, und wenn sich die Rahmenbedingungen ändern, ändert man auch das Statement.
Grüße
Klaus
yo,
die frage kommt von der anderen seite, nämlich welchen nachteil habe ich, wenn ich einen künstlichen pk einsetze ?
die antwort ist einfach, gar keinen nachteil, gegenüber einer aussage, ich bin mir heute sicher, dass sich der pk mit inhalt nicht verändern wird. aber morgen.....
mit anderen worten, mit der einen methode habe ich 100% sicherheit, mit der anderen muss ich aussagen über die zukunft treffen.
Ilja