GROUP_CONCAT in Subquery

GROUP_CONCAT in Subquery

am 02.06.2007 13:53:23 von Christoph Schmidt

Hallo,
ich habe hier zwei Tabellen, objekt und objekt_seite (MySQL 5.0).

Vereinfacht hat die objekt-Tabelle die Felder:

-------------------------------------
| objekt_id | bezeichnung |
-------------------------------------
1 test1
2 test2
3 test3

Die objekt_seite-Tabelle sieht so aus:

-------------------------------------
| objekt_id | seite_id |
-------------------------------------
1 3
2 3
3 4
1 5

Nun habe ich versuch mit

SELECT objekt_id, bezeichnung
FROM objekt
WHERE objekt_id IN (SELECT GROUP_CONCAT(objekt_id SEPARATOR ',')
FROM objekt_seite
WHERE seite_id = 3)

die Objekte mit der ID 1 und 2 auszulesen.

Das liefert mir aber nur das Objekt mit der ID 1.

Ein

SELECT objekt_id, bezeichnung
FROM objekt
WHERE objekt_id IN (1,2) dagegen funktioniert.

Dsa Subquery allein liefert auch 1,2.

Hat jemand eine Idee warum das nicht das erwünschte Ergebnis liefert?

Danke und Gruss

Christoph

Re: GROUP_CONCAT in Subquery

am 02.06.2007 14:31:39 von Dominik Echterbruch

Christoph Schmidt schrieb:
>
> object
> -------------------------------------
> | objekt_id | bezeichnung |
> -------------------------------------
> 1 test1
> 2 test2
> 3 test3
>
> object_seite
> -------------------------------------
> | objekt_id | seite_id |
> -------------------------------------
> 1 3
> 2 3
> 3 4
> 1 5
>
> SELECT objekt_id, bezeichnung
> FROM objekt
> WHERE objekt_id IN (SELECT GROUP_CONCAT(objekt_id SEPARATOR ',')
> FROM objekt_seite
> WHERE seite_id = 3)

Da hätte ich gewisse Bedenken, daß ein Cast des Ergebnisses des
Subselects stattfindet. Oder auf Deutsch: Die Unterabfrage liefert eine
Zeichenkette, IN erwartet aber eine Liste von Zahlen. Also wird MySQL
die Zeichenkette "1,2" in eine Zahl zu wandeln versuchen (hier wäre
vermutlich eine Fehlermeldung besser, als ein impliziter Cast), was
scheinbar 1 ergibt.

Was du wirklich machen willst, ist ein simpler JOIN der beiden Tabellen
mit einer einschränkenden Bedingung:
SELECT o.object_id, o.bezeichnung
FROM object o
INNER JOIN object_seite os ON os.objekt_id = o.object_id
WHERE os.seite_id = 3

Und noch ein Tipp am Rande: versuche entweder englische ODER deutsche
Bezeichnungen zu verwenden. Das zu mischen bringt nur Verwirrung und
macht den Kram schwer wartbar.

Grüße,
Dominik
--
Wo kämen wir denn hin, wenn jeder sagen würde wo kämen wir hin, aber
niemand gehen würde um zu sehen, wohin wir kämen, wenn wir gingen?
(Autor unbekannt)

Re: GROUP_CONCAT in Subquery

am 02.06.2007 15:27:57 von Christoph Schmidt

Dominik Echterbruch schrieb:

> Was du wirklich machen willst, ist ein simpler JOIN der beiden Tabellen
> mit einer einschränkenden Bedingung:
> SELECT o.object_id, o.bezeichnung
> FROM object o
> INNER JOIN object_seite os ON os.objekt_id = o.object_id
> WHERE os.seite_id = 3

Main Ansatz ist dagegen ja von hinten durch die Brust ins Auge. Ich muss
mir die Joins noch mal verinnerlichen.

> Und noch ein Tipp am Rande: versuche entweder englische ODER deutsche
> Bezeichnungen zu verwenden. Das zu mischen bringt nur Verwirrung und
> macht den Kram schwer wartbar.

Stimmt, ist aber nur im Beispiel entstanden.

> Grüße,
> Dominik

Danke und Gruss
Christoph

Re: GROUP_CONCAT in Subquery

am 03.06.2007 10:02:02 von Sven Paulus

Christoph Schmidt wrote:
> SELECT objekt_id, bezeichnung
> FROM objekt
> WHERE objekt_id IN (SELECT GROUP_CONCAT(objekt_id SEPARATOR ',')
> FROM objekt_seite
> WHERE seite_id = 3)

Viel einfacher, Subselects machen das schon von sich aus richtig:

SELECT objekt_id, bezeichnung
FROM objekt
WHERE objekt_id IN (SELECT objekt_id
FROM objekt_seite
WHERE seite_id = 3)

> SELECT objekt_id, bezeichnung
> FROM objekt
> WHERE objekt_id IN (1,2) dagegen funktioniert.

SELECT objekt_id, bezeichnung
FROM objekt
WHERE objekt_id IN ('1,2')

dagegen aber nicht, denn genau das hast Du mit Deinem obigen Query gebaut.

Re: GROUP_CONCAT in Subquery

am 03.06.2007 12:53:34 von Christoph Schmidt

Sven Paulus schrieb:
> Christoph Schmidt wrote:
>> SELECT objekt_id, bezeichnung
>> FROM objekt
>> WHERE objekt_id IN (SELECT GROUP_CONCAT(objekt_id SEPARATOR ',')
>> FROM objekt_seite
>> WHERE seite_id = 3)
>
> Viel einfacher, Subselects machen das schon von sich aus richtig:
>
> SELECT objekt_id, bezeichnung
> FROM objekt
> WHERE objekt_id IN (SELECT objekt_id
> FROM objekt_seite
> WHERE seite_id = 3)

Was wäre denn aus Performancesicht geeigneter, der JOIN oder das
Subselect? Die Tabelle objekt_seite hat einen mehrspaltigen Index über
die Spalten objekt_id und seite_id.

Gruss

Christoph

Re: GROUP_CONCAT in Subquery

am 03.06.2007 13:22:34 von Dominik Echterbruch

Christoph Schmidt schrieb:
>>
>> Viel einfacher, Subselects machen das schon von sich aus richtig:
>>
>> SELECT objekt_id, bezeichnung
>> FROM objekt
>> WHERE objekt_id IN (SELECT objekt_id
>> FROM objekt_seite
>> WHERE seite_id = 3)
>
> Was wäre denn aus Performancesicht geeigneter, der JOIN oder das
> Subselect? Die Tabelle objekt_seite hat einen mehrspaltigen Index über
> die Spalten objekt_id und seite_id.

Ich bevorzuge in der Regel den Join. Zum Einen aus Gewohnheit, zum
Anderen, weil sie früher deutlich schneller waren, als Subselects. Aber
MySQL hat im Laufe der letzten Versionen die Subselects stark optimiert,
sodaß ich (ungetestet) sagen würde, es gibt keinen nennenswerten
Unterschied mehr.

Es gibt aber auch Fälle, in denen ein Subselect deutlich schneller sein
kann, weil der Optimizer besser erkennt, wie er sinnvoll optimieren
kann. Was in deinem konkreten Fall besser ist, kannst du nur durch eine
Testreihe herausfinden.

Aber eine ganz andere Frage: Um wieviele Datensätze dreht es sich da?
Ein paar tausend pro Tabelle? Dann wirst du den Unterschied vermutlich
nicht mal sinnvoll messen können.

Was den kombinierten Index angeht, würde ich mal ein EXPLAIN auf die
Anfrage los lassen. Wird der Index genutzt? Grenzt er das Ergebnis sehr
stark ein? Würden getrennte Indizes auf den Spalten mehr Zeilen aus der
Ergebnismenge ausschließen?

Grüße,
Dominik
--
Wo kämen wir denn hin, wenn jeder sagen würde wo kämen wir hin, aber
niemand gehen würde um zu sehen, wohin wir kämen, wenn wir gingen?
(Autor unbekannt)

Re: GROUP_CONCAT in Subquery

am 03.06.2007 15:52:59 von Sven Paulus

Christoph Schmidt wrote:
> Was wäre denn aus Performancesicht geeigneter, der JOIN oder das=20
> Subselect? Die Tabelle objekt_seite hat einen mehrspaltigen Index über=
=20
> die Spalten objekt_id und seite_id.

Instinktiv wuerde ich zum JOIN greifen, das ist quasi eigentlich die
Musteranwendung eines JOINs, die Du da hast.