Mailinglisten-Archive |
Manuel Hossfeld wrote:
> ich habe hier eine datenbankbasierte PHP-Anwendung, bei der unter anderem eine
> Liste von Dokumenten angezeigt wird. Diese Dokumente haben ID und Version als
> kombinierten primary key (d.h. es können also mehrere Versionen ein und
> desselben Doks vorhanden sein). Nun will ich aber, daß per Default nur die
> jeweils neueste Version jedes Doks angezeigt wird.
mysql> desc doc;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| ver | int(11) | | PRI | 0 | |
| daten | varchar(127) | | | | |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
mysql> select * from doc;
+----+-----+--------------+
| id | ver | daten |
+----+-----+--------------+
| 1 | 1 | doc 1 ver 1 |
| 1 | 2 | doc 1 ver 2 |
| 2 | 10 | doc 2 ver 10 |
| 2 | 15 | doc 2 ver 15 |
+----+-----+--------------+
4 rows in set (0.00 sec)
Dann kannst Du
mysql> select max(ver) as neuver
-> from doc
-> where id = 1
-> group by id;
+--------+
| neuver |
+--------+
| 2 |
+--------+
1 row in set (0.00 sec)
um die maximale Versionsnummer zu einem Dokument $suchid herauszufinden.
Weiter kannst Du auch
mysql> select id, max(ver) as neuver
-> from doc
-> group by id;
+----+--------+
| id | neuver |
+----+--------+
| 1 | 2 |
| 2 | 15 |
+----+--------+
2 rows in set (0.00 sec)
um eine Liste aller Dokument mit ihren jeweils neuesten Versionen
zu bekommen. Aber wie man leicht sieht, geht
mysql> select id, max(ver) as neuver, daten
-> from doc
-> group by id;
+----+--------+--------------+
| id | neuver | daten |
+----+--------+--------------+
| 1 | 2 | doc 1 ver 1 |
| 2 | 15 | doc 2 ver 10 |
+----+--------+--------------+
2 rows in set (0.00 sec)
ins Auge. Mit einem Selfjoin könntest Du jedoch auch die anderen
Daten dieser Dokumente bekommen, wenn man in einem where group
functions verwenden könnte:
mysql> select s.*
-> from doc as p, doc as s
-> where p.id = s.id and s.ver = max(p.ver)
-> group by p.id;
ERROR 1111: Invalid use of group function
Was leider nicht geht. Man kann natürlich voll ausmultiplizieren
und dann mit HAVING arbeiten, aber effizent ist das nicht.
> Zu allem Überfluss hätte ich das ganze auch noch am liebsten in möglichst
> DB-unabhängigem SQL, d.h. irgendwelche "proprietären" Erweiterungen kommen nicht
> in Betracht, da das Skript unverändert (dank PHPLIB) gegen MySQL und ODBC läuft.
Mit einem Subselect könnte man es vielleicht hinbekommen,
aber MySQL kann keine Subselects:
mysql> select id, max(ver) as neuver
-> from doc
-> group by id;
+----+--------+
| id | neuver |
+----+--------+
| 1 | 2 |
| 2 | 15 |
+----+--------+
2 rows in set (0.00 sec)
liefert ja was Du brauchst, also willst Du ja alle Datensätze in
denen die von dem o.a. SQL gefundenen Key verwendet werden:
select * from doc
where id = ( select id from doc group by id )
and ver = ( select max(ver) from doc group by id);
Kristian
--
Kristian Köhntopp, NetUSE Kommunikationstechnologie GmbH
Siemenswall, D-24107 Kiel, Germany, +49 431 386 436 00
Using PHP3? See our web development library at
http://phplib.shonline.de/ (GPL)
php::bar PHP Wiki - Listenarchive