knifflige SQL Abfrage
am 22.12.2005 15:58:01 von weisenbacher
Hallo zusammen,
ich komme im Moment mit meiner SQL-Abfrage nicht weiter. Ich habe eine
Tabelle A mit Veranstaltungen über 'id'-Feld eindeutig gekennzeichnet.
Dazu eine weitere Tabelle B in der weitere Attribute jeder
Veranstaltung enthalten sind. Dabei kann eine Veranstaltung mehrere
Attribute in B haben. Die Tabellen sind mit 'id' und 'entryid'
verknüpft.
Die Tabelle B hat drei Spalten (entryid, property, value). Nun möchte
ich nur Veranstaltungen aus A haben, die einen bestimmten Eintrag in B
NICHT haben. So sieht meine Abfrage bisher aus:
SELECT * FROM A a LEFT JOIN B b ON a.id =3D b.entryid WHERE b.property
NOT LIKE 'mehrtaegig' GROUP by a.id
Das Ergebnis ist, er zeigt mir die Einträge, die 'mehrtaegig' als
Attribut haben trotzdem an! Weil, jede Veranstaltung hat
standardmässig zwei gleiche Einträge (z.B 'rot', 'blau') in der
Spalte 'property' in Tabelle B, sodass die Veranstaltungen, welche
'mehrtägig' als Attribut haben, trotzdem mitkommen, weil sie auch
'blau' und 'rot' sind. Wie kann ich denn ausschliessen, dass alle
Veranstaltungen mitkommen, ausser denen, die mehrtaegig als Attribut
haben?
Hat jemand eine Idee? Ich wäre dankbar
Gruss
Stefan
Re: knifflige SQL Abfrage
am 22.12.2005 16:11:19 von Dominik Echterbruch
weisenbacher@googlemail.com wrote:
>
> Tabelle A mit Veranstaltungen über 'id'-Feld eindeutig gekennzeichnet.
>
> Die Tabelle B hat drei Spalten (entryid, property, value). Nun möchte
> ich nur Veranstaltungen aus A haben, die einen bestimmten Eintrag in B
> NICHT haben. So sieht meine Abfrage bisher aus:
>
> SELECT * FROM A a LEFT JOIN B b ON a.id = b.entryid WHERE b.property
> NOT LIKE 'mehrtaegig' GROUP by a.id
Ja, das hab ich früher auch probiert. Kann aber nicht funktionieren (wie
du es möchtest). Probier mal:
SELECT * FROM A a
LEFT JOIN B b ON a.id = b.entryid AND b.property = 'mehrtaegig'
WHERE b.entryid IS NULL
Der LEFT JOIN sucht dir alle passenden Datensätze raus und NULL für die
Zeilen in A, für die es keine passende Zeilen in B gibt. Darauf muß man
nur noch filtern und fertig.
Grüße,
Dominik
--
MonstersGame - Die Schlacht zwischen Vampiren und Werwölfen
http://spielwelt6.monstersgame.net/?ac=vid&vid=3018786
Re: knifflige SQL Abfrage
am 22.12.2005 16:12:48 von Andreas Lange
Am 22.12.2005, 15:58 Uhr, schrieb :
> [ snipped intro ]
> Die Tabelle B hat drei Spalten (entryid, property, value). Nun möchte
> ich nur Veranstaltungen aus A haben, die einen bestimmten Eintrag in B
> NICHT haben. So sieht meine Abfrage bisher aus:
>
> SELECT * FROM A a LEFT JOIN B b ON a.id = b.entryid WHERE b.property
> NOT LIKE 'mehrtaegig' GROUP by a.id
>
> Das Ergebnis ist, er zeigt mir die Einträge, die 'mehrtaegig' als
> Attribut haben trotzdem an! Weil, jede Veranstaltung hat
> standardmässig zwei gleiche Einträge (z.B 'rot', 'blau') in der
> Spalte 'property' in Tabelle B, sodass die Veranstaltungen, welche
> 'mehrtägig' als Attribut haben, trotzdem mitkommen, weil sie auch
> 'blau' und 'rot' sind. Wie kann ich denn ausschliessen, dass alle
> Veranstaltungen mitkommen, ausser denen, die mehrtaegig als Attribut
> haben?
>
> Hat jemand eine Idee? Ich wäre dankbar
So aus dem Bauch heraus:
SELECT *
FROM A
LEFT JOIN B ON a.id = b.entryid AND b.property = 'mehrtaegig'
WHERE b.entryid IS NULL
> Gruss
> Stefan
>
--
Andreas Lange
Re: knifflige SQL Abfrage
am 27.12.2005 09:45:38 von weisenbacher
Dominik Echterbruch schrieb:
> weisenbacher@googlemail.com wrote:
> >
> > Tabelle A mit Veranstaltungen über 'id'-Feld eindeutig gekennzeichnet.
> >
> > Die Tabelle B hat drei Spalten (entryid, property, value). Nun möchte
> > ich nur Veranstaltungen aus A haben, die einen bestimmten Eintrag in B
> > NICHT haben. So sieht meine Abfrage bisher aus:
> >
> > SELECT * FROM A a LEFT JOIN B b ON a.id =3D b.entryid WHERE b.property
> > NOT LIKE 'mehrtaegig' GROUP by a.id
>
> Ja, das hab ich früher auch probiert. Kann aber nicht funktionieren (wie
> du es möchtest). Probier mal:
>
> SELECT * FROM A a
> LEFT JOIN B b ON a.id =3D b.entryid AND b.property =3D 'mehrtaegig'
> WHERE b.entryid IS NULL
>
> Der LEFT JOIN sucht dir alle passenden Datensätze raus und NULL für d=
ie
> Zeilen in A, für die es keine passende Zeilen in B gibt. Darauf muß m=
an
> nur noch filtern und fertig.
--- Hallo Dominik,
danke für den Tipp; diese Idee hatte ich auch schon, aber ich habe es
so nicht hinbekommen. Möglicherweise vermag ich einfach nicht den
richtigen Filter anzuwenden. Wenn ich die Abfrage oben so anwende, dann
bekomme ich trotzdem alle Datensätze geliefert.
Das liegt glaube ich daran, wie ich versucht habe zu erklären, dass
jeder Datensatz von A in B standardmässig zwei Einträge hat - ich
nenne sie mal 'rot' und 'blau'. Und weil es eben dadurch immer eine
passende Zeile in B gibt für jeden Datensatz, liefert er mir alle. Ich
weiss momentan nicht wie ich die aus dem SQL-Satz ausschliessen kann,
die nicht nur rot und blau haben, sondern auch 'mehrtaegig'. Folgende
Abfrage funktioniert zum Beispiel auch nicht:
SELECT * FROM A a
LEFT JOIN B b ON a.id =3D b.entryid AND b.property =3D 'mehrtaegig' AND
bproperty =3D 'rot' AND b.property =3D 'blau'
WHERE b.entryid IS NULL
Das Ergebnis ist null - kein Datensatz wird gefunden.
Danke & Gruss
Stefan
Re: knifflige SQL Abfrage
am 27.12.2005 10:38:45 von Dominik Echterbruch
weisenbacher@googlemail.com wrote:
>>
>>>Tabelle A mit Veranstaltungen über 'id'-Feld eindeutig gekennzeichnet.
>>>
>>>Die Tabelle B hat drei Spalten (entryid, property, value). Nun möchte
>>>ich nur Veranstaltungen aus A haben, die einen bestimmten Eintrag in B
>>>NICHT haben. So sieht meine Abfrage bisher aus:
>>>
>>>SELECT * FROM A a LEFT JOIN B b ON a.id = b.entryid WHERE b.property
>>>NOT LIKE 'mehrtaegig' GROUP by a.id
>>
>>Ja, das hab ich früher auch probiert. Kann aber nicht funktionieren (wie
>>du es möchtest). Probier mal:
>>
>>SELECT * FROM A a
>>LEFT JOIN B b ON a.id = b.entryid AND b.property = 'mehrtaegig'
>>WHERE b.entryid IS NULL
>
> danke für den Tipp; diese Idee hatte ich auch schon, aber ich habe es
> so nicht hinbekommen. Möglicherweise vermag ich einfach nicht den
> richtigen Filter anzuwenden. Wenn ich die Abfrage oben so anwende, dann
> bekomme ich trotzdem alle Datensätze geliefert.
Das halte ich für ein Gerücht:
test=# SELECT * FROM a;
id
----
1
2
3
(3 rows)
test=# SELECT * FROM b;
entryid | property
---------+------------
1 | rot
1 | blau
2 | rot
2 | blau
3 | rot
3 | blau
3 | mehrtaegig
(7 rows)
test=# SELECT * FROM a LEFT JOIN b ON a.id = b.entryid AND b.property =
'mehrtaegig' WHERE b.entryid IS NULL;
id | entryid | property
----+---------+----------
1 | |
2 | |
(2 rows)
Ist zwar jetzt PostgreSQL (hatte ich gerade noch offen), aber MySQL
verhält sich in diesem Fall exakt identisch.
Wenn das also nicht funktioniert, liegt es irgendwo an deinen Daten,
deiner (falsch wiedergegebenen?) Tabellenstruktur oder daran, daß du das
Statement nochmal verändert hast.
Poste doch mal die Tabellenstruktur (SHOW CREATE TABLE ) und
ein paar korrespondierende Daten aus A und B.
> Das liegt glaube ich daran, wie ich versucht habe zu erklären, dass
> jeder Datensatz von A in B standardmässig zwei Einträge hat - ich
> nenne sie mal 'rot' und 'blau'.
Nein, genau das wird durch das "property = 'mehrtaegig'" im ON-Statement
des LEFT JOINs ausgeschlossen. Einzige Möglichkeit: es gibt tatsächlich
für alle Daten in A einen Datensatz in B mit property = 'mehrtaegig'.
> Folgende Abfrage funktioniert zum Beispiel auch nicht:
>
> SELECT * FROM A a
> LEFT JOIN B b ON a.id = b.entryid AND b.property = 'mehrtaegig' AND
> b.property = 'rot' AND b.property = 'blau'
> WHERE b.entryid IS NULL
>
> Das Ergebnis ist null - kein Datensatz wird gefunden.
Kein Wunder. Ein Datensatz in B kann ja unmöglich gleichzeitig blau, rot
und mehrtaegig in der property-Spalte stehen haben.
Grüße,
Dominik
--
MonstersGame - Die Schlacht zwischen Vampiren und Werwölfen
http://spielwelt6.monstersgame.net/?ac=vid&vid=3018786
Re: knifflige SQL Abfrage
am 28.12.2005 10:09:39 von weisenbacher
> Das halte ich für ein Gerücht:
Hallo Dominik,
mea maxima culpa ;). Ich hatte tatsächlich einen Fehler in Syntax. Das
Feld hiess nicht 'mehrtaegig' sondern 'ep_mehrtaegig. Und dann gings...
Vielen Dank & Grüsse
Stefan