• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

mySQL DB-Abfrage

lonely_hawk

New member
hallo,

bastle an einer Seite mit zum Teil (zumindest für mich) komlexeren DB-Abfragen.

Jetzt habe ich offenbar einen Knoten im Kopf und komm nicht weiter.

Aufbau meiner Tabelle

id | id_tab2 | id_tab3 | Datum

Dabei darf die Kombination von id_tab2 und id_tab3 mehrmals auftreten.
Die Kombination von id_tab2 und id_tab3 und Datum nur jeweils einmal.

Nun benötige ich die id_tab3 aller Kombinationen von id_tab2 und id_tab3 wo jeweils das Datum am neusten ist.

Bsp.:

id | id_tab2 | id_tab3 | Datum
01 123 247 2002-01-01
02 456 233 2002-01-01
03 789 103 2002-12-01
04 789 103 2002-06-01
05 789 103 2002-01-01

06 429 303 2002-06-01
07 429 303 2002-01-01

08 147 403 2002-01-01

Und als Ausgabe brauche ich:

id | id_tab2 | id_tab3 | Datum
01 123 247 2002-01-01
02 456 233 2002-01-01
03 789 103 2002-12-01
06 429 303 2002-06-01

08 147 403 2002-01-01

Mit
Code:
SELECT id_tab3 FROM tab WHERE id_tab2 = '$var'
frag ich ja nun nach allen id_tab3 bei denen id_tab2 = $var. Wie nun schon werwähnt benötige ich aber immer nur die wo das datum bei der gleichen kombination von id_tab2 und id_tab3 am neusten ist. Hab u.a. mit MAX(Datum) rumprobiert, aber so richtig will das nicht. Vielleicht seh ich auch den Wald vor lauter Bäumen nicht...

Hat hier jemand einen Vorschlag?
 
Zuletzt bearbeitet:
Warum HAVING?

Code:
SELECT `id`, `id_tab2` , `id_tab3`, max(`Datum`)
FROM `table`
GROUP BY `id_tab2`, `id_tab3`
 
Dabei darf die Kombination von id_tab2 und id_tab3 mehrmals auftreten.

...
Code:
SELECT id_tab3 FROM tab WHERE id_tab2 = '$var'
weil er, soweit ich das verstanden habe, die "id_tab3" sucht, wo "id_tab2" seinem $var entspricht und das neueste Datum hat.

EDIT: achso, jetzt weiß ich wass du sagen willst, ja, so geht es natürlich auch.
 
Zuletzt bearbeitet:
hallo, danke erstmal für die Antworten, und danke für den Link @hesst, die seite kannte ich noch nicht, hat mir aber viele fragen beantwortet.

nun zum problem:

Code:
SELECT `id`, `id_tab2` , `id_tab3`, max(`Datum`)
FROM `table`
GROUP BY `id_tab2`, `id_tab3`

führt leider zu dieser tabelle:

id_tab2 id_tab3 max(datum)
137 21 2005-02-01
17 55 2005-04-01
41 55 2005-02-01
63 55 2002-01-01
80 55 2007-02-01
88 55 2004-04-01

105 56 2004-06-01
51 58 0000-00-00
83 59 0000-00-00
17 64 2005-02-01
[....]

Statt nur den Datensatz mit dem höchsten Datum werden alle Sätze ausgegeben. (id_tab3 = 55)
 
häng
Code:
LIMIT 1
hinten dran

;)

nein, das hat keinen sinn. dann wird mir nur der letzte Datensatz der gesammten Abfrage angezeitg. Mir geht es um den letzen Datensatz mit der gleichen id. Die Nachfolgenden Datensätze mit anderen ids sollen natürlich angezeigt werden...

Trotzdem danke.

Nachtrag:
---------

Ich hab das Problem erstmal etwas unsauber gelöst, damit ich weiter machen kann, in dem ich bei der MySQL Abfrage unter anderem nach id und Datum der Reihenfolge nach sortieren lasse, und dann per php überprüfe ob die letzte id gleich der aktuellen ist. Ist das der Fall, wird der Datensatz nicht angezeigt... ist natürlich mist... weil ja so mehr Datensätze abgerufen werden müssen als eigentlich gewollt. also falls jemanden noch was einfällt bin ich dankbar. sonst muss ich mich da mal mit befassen wenn ich mehr zeit (& nerven) habe.
 
Zuletzt bearbeitet:
ich bin mir jetzt nicht mehr sicher, was du eigentlich suchst.

SELECT id_tab3 FROM tab WHERE id_tab2 = $var GROUP BY id_tab2, id_tab3 HAVING MAX(Datum);

nicht? bzw. ZeitGeists vorschlag

SELECT id, id_tab2, id_tab3, MAX(Datum) FROM tab WHERE id_tab2 = $var GROUP BY id_tab2, id_tab3;
 
wie oben schon geschrieben, liefern beide Anfragen das 'falsche Ergebnis'.

[...] führt leider zu dieser tabelle:

id_tab2 id_tab3 max(datum)
137 21 2005-02-01
17 55 2005-04-01
41 55 2005-02-01
63 55 2002-01-01
80 55 2007-02-01
88 55 2004-04-01

105 56 2004-06-01
51 58 0000-00-00
83 59 0000-00-00
17 64 2005-02-01

[....]

Statt nur den Datensatz mit dem höchsten Datum werden alle Sätze ausgegeben. (id_tab3 = 55)

Ich benötig nur die grünen Datensätze also von jeder id_tab3 nur einen Datansatz und zwar den mit dem höchsten datum.

------

ich bin mir jetzt nicht mehr sicher, was du eigentlich suchst.

SELECT id_tab3 FROM tab WHERE id_tab2 = $var GROUP BY id_tab2, id_tab3 HAVING MAX(Datum);

nicht? bzw. ZeitGeists vorschlag

SELECT id, id_tab2, id_tab3, MAX(Datum) FROM tab WHERE id_tab2 = $var GROUP BY id_tab2, id_tab3;
 
Wie auch schon oben gesagt ist LIMIT 1 hier fehl am Platz. Ich möchte ja nicht nur einen Datensatz... sondern viele. Nur möchte ich, dass id_tab3 nicht mehrfach erscheint. Und Falls id_tab3 mehrfach in der Tabelle ist, soll er mir den Datensatz ausgeben, wo das Datum am neusten ist. ich weis nicht, wie ich das noch anders deutlich machen kann...

ja, logisch, mein fehler.
SELECT id, id_tab2, id_tab3, MAX(Datum) FROM tab WHERE id_tab2 = $var GROUP BY id_tab2, id_tab3 ORDER BY datum DESC LIMIT 1;
 
Wie auch schon oben gesagt ist LIMIT 1 hier fehl am Platz. Ich möchte ja nicht nur einen Datensatz... sondern viele. Nur möchte ich, dass id_tab3 nicht mehrfach erscheint. Und Falls id_tab3 mehrfach in der Tabelle ist, soll er mir den Datensatz ausgeben, wo das Datum am neusten ist. ich weis nicht, wie ich das noch anders deutlich machen kann...

??? du suchst also nicht nach id2=var?

versuchs mal damit
SELECT * FROM tab AS x WHERE Datum = (SELECT MAX(Datum) FROM tab WHERE id_tab3 = x.id_tab3);

aber vielleicht fällt einem experten hier noch was besseres ein
 
Mit dem geänderten Beispiel ist die HAVING-Clausel doch nötig. Ich dachte du brauchst "nur" den höchsten Wert für eine eindeutige Kombination der beiden ids. Aber wenn ich das richtig verstehe, möchtest du ja für jede tab3_id das Tupel mit dem höchsten Datum haben.

Code:
SELECT * FROM tab
GROUP BY tab3_id
HAVING datum = MAX(datum)
 
Zuletzt bearbeitet:
Mit dem geänderten Beispiel ist die HAVING-Clausel doch nötig.

das ist witzig, da ich mittlerweile der meinung bin, daß ich mit meiner HAVING-Clausel total daneben lag. laut SQL-standard ist sie nur auf felder der GROUP BY clausel anwendbar, MySQL erlaubt es zwar auch auf andere spalten, diese müssen aber innerhalb der Gruppe konstant sein.
MySQL :: MySQL 5.0 Reference Manual :: 11.11.3 GROUP BY and HAVING with Hidden Columns

und im test kommt auch mist raus
Code:
mysql> SELECT * FROM xxx;
+------+------+------+------------+
| id   | id2  | id3  | datum      |
+------+------+------+------------+
|    1 |  123 |  247 | 2002-01-01 |
|    2 |  456 |  233 | 2002-01-01 |
|    3 |  456 |  103 | 2002-12-02 |
|    4 |  456 |  103 | 2002-12-03 |
|    5 |  456 |  103 | 2002-12-01 |
|    6 |  789 |  103 | 2002-12-01 |
|    7 |  789 |  103 | 2002-06-01 |
|    8 |  789 |  103 | 2002-01-01 |
|    9 |  429 |  303 | 2002-06-01 |
|   10 |  429 |  303 | 2002-01-01 |
|   11 |  147 |  403 | 2002-01-01 |
+------+------+------+------------+

Code:
mysql> SELECT * FROM xxx GROUP BY id2, id3 HAVING datum=MAX(datum);
+------+------+------+------------+
| id   | id2  | id3  | datum      |
+------+------+------+------------+
|    1 |  123 |  247 | 2002-01-01 |
|   11 |  147 |  403 | 2002-01-01 |
|    9 |  429 |  303 | 2002-06-01 |
|    2 |  456 |  233 | 2002-01-01 |
|    6 |  789 |  103 | 2002-12-01 |
+------+------+------+------------+

komischerweise fehlt hier die kombination id2=456 und id3=103 komplett!?
 
komischerweise fehlt hier die kombination id2=456 und id3=103 komplett!?
ach so, nicht komisch. durch die group by clausel wird ja
| 3 | 456 | 103 | 2002-12-02 |
in die ergebnisstabelle übernommen, das datum 2002-12-02 ist aber nicht das max-datum aus zeile
| 4 | 456 | 103 | 2002-12-03 |
 
sollte auch so heißen:

SELECT * FROM tab
GROUP BY tab3_id
HAVING datum = MAX(datum)

hej, hab jetzt mal wieder zeit gefunden weiter zu probieren.
leider bin ich nicht schlauer als vorher. um andere fehlerquellen auszuschließen habe ich meinen query auf das minimale reduziert also wie das zitat oben.

das ergebnis finde ich sehr merkwürdig.

hier erstmal ein 'realer' ausschnitt der tabelle:

Code:
(1455, 137, 21, '2005-02-01', '0000-00-00'),
[COLOR="red"](1488, 41, 34, '2005-01-01', '0000-00-00'),
(1489, 146, 34, '2003-07-01', '2004-12-01'),
(1490, 20, 34, '2001-12-01', '2003-06-01'),
(1483, 130, 55, '2007-09-01', '2008-08-01'),
(1471, 84, 55, '2000-01-01', '2004-09-01'),
(1468, 88, 55, '2004-10-01', '2006-02-01'),
(1470, 89, 55, '2006-09-01', '2007-08-01'),[/COLOR]
(1472, 82, 56, '2006-03-01', '2007-07-01'),
(1474, 43, 56, '2008-07-01', '0000-00-00'),
(1458, 105, 56, '2004-06-01', '2006-02-01'),
[COLOR="red"](1452, 51, 58, '2008-05-01', '2008-09-01'),
(1473, 43, 58, '2008-10-01', '0000-00-00'),[/COLOR]
(1454, 83, 59, '2008-04-01', '0000-00-00'),
(1484, 81, 60, '2008-09-01', '0000-00-00'),
(1487, 130, 60, '2005-10-01', '2007-07-01'),
(1486, 56, 60, '2002-08-01', '2005-09-01'),
(1485, 113, 60, '1999-01-01', '2002-07-01'),
(1460, 17, 64, '2005-02-01', '0000-00-00'),
(1475, 143, 1424, '0000-00-00', '0000-00-00'),
(1480, 143, 1479, '0000-00-00', '0000-00-00'),
(1476, 143, 1596, '0000-00-00', '0000-00-00'),
(1478, 143, 1625, '0000-00-00', '0000-00-00'),
(1477, 143, 1631, '0000-00-00', '0000-00-00'),
(1479, 143, 1660, '0000-00-00', '0000-00-00'),
(1481, 143, 1671, '0000-00-00', '0000-00-00'),
(1482, 143, 1693, '0000-00-00', '0000-00-00'),
(1492, 39, 2743, '2007-04-01', '2008-03-01'),
(1491, 63, 2743, '2008-03-01', '2008-08-01');

wenn ich die gepostete abfrage darüber starte erhalte ich folgendes:

Code:
(1455, 137, 21, '2005-02-01', '0000-00-00'),
(1474, 43, 56, '2008-07-01', '0000-00-00'),
(1454, 83, 59, '2008-04-01', '0000-00-00'),
(1484, 81, 60, '2008-09-01', '0000-00-00'),
(1460, 17, 64, '2005-02-01', '0000-00-00'),
(1475, 143, 1424, '0000-00-00', '0000-00-00'),
(1480, 143, 1479, '0000-00-00', '0000-00-00'),
(1476, 143, 1596, '0000-00-00', '0000-00-00'),
(1478, 143, 1625, '0000-00-00', '0000-00-00'),
(1477, 143, 1631, '0000-00-00', '0000-00-00'),
(1479, 143, 1660, '0000-00-00', '0000-00-00'),
(1481, 143, 1671, '0000-00-00', '0000-00-00'),
(1482, 143, 1693, '0000-00-00', '0000-00-00'),
(1491, 63, 2743, '2008-03-01', '2008-08-01');

von den max(datum) einträgen der tab3_id 34,55,58 (oben rot markiert) fehlt also jede spur, scheinbar wahllos, da es bei den anderen tab3_id's klappt und es wird auch wirklich nur das neuste datum angezeigt.

das prinzip funtkioniert also. aber warum fehlen die drei datensätze?

blickt da jemand durch?

p.s. die zweite datum-spalte dürfte hierbei keine rolle spielen, sie wird namentlich ja nirgens angesprochen...
 
das
http://forum.jswelt.de/serverseitige-programmierung/45662-mysql-db-abfrage.html#post288709
willst du nicht nehmen?

das ergebnis finde ich sehr merkwürdig.
steht doch hier:
http://forum.jswelt.de/serverseitige-programmierung/45662-mysql-db-abfrage-2.html#post288932

von den max(datum) einträgen der tab3_id 34,55,58 (oben rot markiert) fehlt also jede spur, scheinbar wahllos, da es bei den anderen tab3_id's klappt und es wird auch wirklich nur das neuste datum angezeigt.

naja, nicht wahllos, das hängt von deiner gruppierung ab. hier wird nach tab3_id gruppiert, damit das geht, müßtest du auch noch nach datum gruppieren, das hilft dir dann allerdings nicht weiter.
stimmt die reihenfolge in deiner realen Tabelle?

das prinzip funtkioniert also. aber warum fehlen die drei datensätze?
http://forum.jswelt.de/serverseitige-programmierung/45662-mysql-db-abfrage-2.html#post288936
 
Zuletzt bearbeitet:
Zurück
Oben