PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : verzwicktes Select



boxa
18-04-2006, 13:56
Hallo Experten!

Ich habe ein Problem bei der Formulierung eines selcet Statements:

Tabelle:
ID | sportart
-------------------------------
1 | schwimmen
1 | fussball
1 | basketball
2 | fussball
2 | basketball
3 | basketball
4 | reiten

Wie bekomme ich aus dieser Tabelle die IDs, wenn ich wissen möchte wer beispielsweise fussball UND basketball spielt? In diesem Fall wäre das Ergebnis 1 und 2.

Die oder Abfrage ist kein Problem. Ich benutze select from TAB where sportart in(...). Wie mach ich das mit der UND-Verknüpfung?

Ganz herzlichen Dank für Eure Hilfe!

Gruß
boxa

ninguno
18-04-2006, 14:18
sollte zb. so gehen:

select distinct id from tab t1
where exists (select null from tab where sportart='fussball' and id=t1.id)
and exists (select null from tab where sportart='basketball' and id=t1.id);

boxa
18-04-2006, 14:31
Danke für die sehr schnelle Antwort. Auf meinem Webserver ist MySQL in der Version 4.0.21 installiert. So wie es aussieht gibt es in dieser Version noch keine Subselects. Gibt es eine andere Möglichkeit die Abfrage zu realsisieren?

BLUESCREEN3D
18-04-2006, 14:37
Ungetestet:

SELECT T1.`ID`
FROM `table` AS T1
JOIN `table` AS T2 ON T1.`ID`=T2.`ID`
WHERE T1.`sportart`='fussball' AND T2.`sportart`='basketball'

boxa
18-04-2006, 14:51
DANKESCHÖN! Es funktioniert!

Turbohummel
18-04-2006, 16:46
Das hier ist performanter, insbesondere wenn du mal nach mehr als 2 Sportarten suchst, sparst du dir damit die unzähligen Joins.



SELECT DISTINCT id
FROM table
WHERE sportart = "basketball" OR sportart = "fussball"
GROUP BY id
HAVING COUNT(id) >= 2;

Romanday
18-04-2006, 19:09
Hallo Experten!

Ich habe ein Problem bei der Formulierung eines selcet Statements:

Tabelle:
ID | sportart
-------------------------------
1 | schwimmen
1 | fussball
1 | basketball
2 | fussball
2 | basketball
3 | basketball
4 | reiten

Gruß
boxa


Wenn wir wieder Rechtschreibreform haben und fussball plötzlich
Fußsball geschrieben wird, mußt du alle Datensätze mit fussball ändern.
Ist das richtig?:D

Jasper
18-04-2006, 22:05
Das hier ist performanter, insbesondere wenn du mal nach mehr als 2 Sportarten suchst, sparst du dir damit die unzähligen Joins.



SELECT DISTINCT id
FROM table
WHERE sportart = "basketball" OR sportart = "fussball"
GROUP BY id
HAVING COUNT(id) >= 2;


setzt vorraus, dass keine kombination von id und sportart doppelt vorkommt.

-j

Turbohummel
19-04-2006, 05:44
Ok, vernünftiges Tabellendesign vorrausgeesetzt. Aber davon bin ich mal ausgegangen.

quinte17
20-04-2006, 14:45
SELECT id
FROM table
WHERE sportart in ( "basketball", "fussball" )
GROUP BY id
HAVING COUNT(1) > 1;

distinct ist überflüssig, da group by.
mit "in" kann man den select einfacher anpassen, da kein "OR = bla" vielfaches vorkommt.
count(1) kann ein wenig schneller sein, da dort der inhalt von id dann nicht mehr abgefragt werden muss.

>1 ist geschmackssache

hier noch eine mögichkeit, um doppelte sportarten bei gleicher id auszuschließen



SELECT id
FROM ( select distinct id, sportart from table ) a
WHERE sportart in ( "basketball", "fussball" )
GROUP BY id
HAVING COUNT(1) > 1;


greetz

Turbohummel
20-04-2006, 17:28
Subselect waren ja nicht möglich.

Das mit dem IN is Geschmackssache, ich häng irgendwie an meinem OR.#

Mit dem Count() hast du unrecht, der SQLOptimizer wirft den inhalt von Count sowieso weg, da er keinen Einfluss hat. ID erhöht nur die Lesbarkeit (bei 20-Zeilen-Querrys sehr sehr wichtig).
Gleiches für das >= 2.

quinte17
20-04-2006, 17:33
des mit dem optimizer wusste ich noch nicht :)
ich habe es halt so gelernt, bei count immer ne 1 reinzuschreiben, weil da ja eh immer die anzahl der zeilen dabei rauskommt, und die information dadrin wirklich egal ist.
>= 2 ist für manche vielleicht lesbarer da hast du recht.
mit dem OR allerdings bin ich der meinung, dass es mit 'IN' schöner ist wenn man mehr als 2 bedingungen hat. da wird dann der select nicht so lang und bleibt verständlicher.

aber die mysql 4.1 kann doch schon derived tables oder etwa nicht? oder bin ich schon wieder zu lange auf 5.x.

greetz

Romanday
20-04-2006, 18:17
Ist nett mal die ganzen SQL Befehle zu sammeln.
(Entdecke die Möglichkeiten :D)

Aber ich halte den Tabellenaufbau für falsch.

Tabelle:
ID | sportart
-------------------------------
1 | schwimmen
1 | fussball
1 | basketball
2 | fussball
2 | basketball
3 | basketball
4 | reiten

Um es noch deutlicher zu machen. Was passiert z. B. wenn in der
Spalte Sportart komplette Sätze eingetragen sind? Dann geht die
Geschwindigkeit in den Keller. Jeder Satz wird dann noch doppelt
und 3x usw. eingetragen, das kann es doch nicht sein!?

quinte17
20-04-2006, 19:06
da hast du ja auch recht :)
diese tabelle ist noch nicht ganz fertig.. aber wollen wir denn hier alles verraten? :p

greetz

prograbbit
25-04-2006, 09:15
Hallo zusammen,

ich habe ein ähnliches Problem wie boxa, allerdings bräuchte ich eine Lösung für eine Abfrage über mehrere Tabellen. Angenommen, ich suche die IDs von Personen, die schwimmen UND Fußball spielen (also so wie bei boxa) UND aber zusätzlich noch die IDs der Personen, die Deutsch UND Englisch sprechen.

Ich habe also 2 Tabellen:
ID | sportart
----------------
1 | schwimmen
1 | fussball
2 | fussball
3 | basketball
...

ID | sprache
----------------
1 | deutsch
1 | englisch
2 | spanisch
3 | deutsch
...

Als Ergebnis des Beispiels oben würde die ID 1 raus kommen.

Gibt es eine Möglichkeit, auch für dieses Problem eine saubere und sichere UND-Abfrage hinzubekommen?

Vielen Dank schon mal!!!

ninguno
25-04-2006, 10:19
du suchst personen die schwimmen UND Fußball spielen UND Deutsch UND Englisch sprechen?
oder du suchst a) personen die schwimmen UND Fußball spielen und b) noch zusätzlich solche die Deutsch UND Englisch sprechen?

quinte17
25-04-2006, 11:30
ich glaube er meint das erstere

prograbbit
25-04-2006, 13:36
hallo,

ich suche ersteres, also Personen die schwimmen UND Fußball spielen UND Deutsch UND Englisch sprechen.

Was nach ein paar Tests funktioniert, ist die Aneinanderreihung etlicher joins. Ich frag mich nur, ob es auch eine elegantere und schnellere Abfrage gibt...

ninguno
25-04-2006, 14:38
mit ein paar subselects gings auch, falls dein mysql das unterstützt:

select distinct id from sportart t1
where sportart='fussball'
and exists (select null from sportart where sportart='basketball' and id=t1.id)
and exists (select null from sprache where sprache='deutsch' and id=t1.id)
and exists (select null from sprache where sprache='englisch' and id=t1.id);

BLUESCREEN3D
25-04-2006, 19:02
Immer diese Subselects...

Für die Einbeziehung der zweiten Tabelle kannst du einfach einen der oben beschriebenen Queries um einen JOIN erweitern.

ninguno
25-04-2006, 21:10
joins wollte er ja nicht und ich finde dass subselects leichter verständlich sind als join-ketten. und was ein vernünftiges datenbanksystem wie oracle unter der haube daraus macht wieder ganz was anderes

BLUESCREEN3D
25-04-2006, 23:12
joins wollte er ja nicht
Genau den Satz hatte ich überlesen :D

quinte17
26-04-2006, 10:51
Was nach ein paar Tests funktioniert, ist die Aneinanderreihung etlicher joins. Ich frag mich nur, ob es auch eine elegantere und schnellere Abfrage gibt...
ob es in diesem fall eleganter ist auf joins zu verzichten ist wohl fraglich.
geschwindigkeit würde ein index bringen (falls die id nicht eh schon primary key ist)
ansonsten den querryplan mal anschauen, um herauszufinden was da genau langsam ist

greetz

Turbohummel
29-04-2006, 07:08
joins wollte er ja nicht und ich finde dass subselects leichter verständlich sind als join-ketten. und was ein vernünftiges datenbanksystem wie oracle unter der haube daraus macht wieder ganz was anderes

Oracle verlangsamt sogar ein
SELECT * FROM table WHERE 1;
gegenüber einem
SELECT * FROM table;

MySQL, MaxDB oder MS SQLServer.

Wenn man Zeit hat, kann man ja Oracle oder Cloudscape einsetzen.

Jasper
29-04-2006, 16:00
Oracle verlangsamt sogar ein
SELECT * FROM table WHERE 1;
gegenüber einem
SELECT * FROM table;


?? das erste statement ist auch kein gültiges SQL, damti ist es unendlich langsamer.

-j

Turbohummel
01-05-2006, 07:03
Doch, ist es. Funzt in jedem DBMS und 1 ist als "TRUE" in SQL 92, 99 und 03 definiert.

Jasper
01-05-2006, 08:45
SQL> select * from a where 1;
select * from a where 1
*
ERROR at line 1:
ORA-00920: invalid relational operator

deathb
01-05-2006, 09:37
prograbit: gibt doch mal die komplette DB. Oder den Teil raus der deine 2 Tabellen kompletiert....wegen dem Tabellen Design ob das nicht einfacher geht.
Sinn und Zweck eines RDBMS ist ja auch redundanzen zu vermeiden.

Julius