mySQL: Nach Kommaseperiete Einträgen suchen
lixx
- datenbank
Hi Leut',
Ich hätte da eine Frage bezüglich einer MySQL-Abfrage.
Die DB hat die Tabellen users und groups. In der Eingabemaske kann man dem User mehrere Gruppen zuteilen, deren groups.id dann in das Feld users.groups_id als Kommaseperierter String eingetragen wird (15,56,54, etc.).
Wie man danach sucht habe ich schon hingekriegt. Die Frage ist nur, wie sieht eine Abfrage aus, wenn ich nach allen Benutzer suchen möchte, die sich in keiner Gruppe befinden?
WHERE users.groups_id = ''
... geht leider nicht. Weil wenn man einige Gruppen löscht, dann befindet sich die groups.id noch immer in users.groups_id.
Völlig falsch das folgende Beispiel ;) aber es macht vielleicht deutlich was ich meine:
SELECT * FROM users, groups
WHERE NOT FIND_IN_SET( groups.id, users.groups_id )
lg lixx
hi,
Die Frage ist nur, wie sieht eine Abfrage aus, wenn ich nach allen Benutzer suchen möchte, die sich in keiner Gruppe befinden?
WHERE users.groups_id = ''
... geht leider nicht.
Was für einen Inhalt hat das Feld denn, wenn der User sich in keiner Gruppe befindet - wirklich einen Leerstring, oder vielleicht NULL?
Auf NULL-Werte musst du mit IS NULL abfragen.
gruß,
wahsaga
Die DB hat die Tabellen users und groups. In der Eingabemaske kann man dem User mehrere Gruppen zuteilen, deren groups.id dann in das Feld users.groups_id als Kommaseperierter String eingetragen wird (15,56,54, etc.).
Wie man danach sucht habe ich schon hingekriegt. Die Frage ist nur, wie sieht eine Abfrage aus, wenn ich nach allen Benutzer suchen möchte, die sich in keiner Gruppe befinden?
WHERE users.groups_id = ''
Mal ganz davon abgesehen, dass die "n:m" zwischen 'users' und 'groups' etwas blass implementiert ist, ist doch davon auszugehen, dass das DF 'users.groups_id' den Wert '()' bzw. '(,)' oder '' hat, wenn es "leer" ist. Also die WHERE-Klausel anpassen.
Evebutell auch mal in der Doku nach den Stringfunktionen von MySQL schauen...
yo,
zum einen ist der hinweis von hamster ganz wichtig, nämlich eine dritte beziehungstabelle zu bilden. dann hättest du jetzt erst gar nicht diese probleme. aber jedem seinen willen, hier eine eventuelle lösung, wobei es immer interessant ist, die version deines dbms zu kennen:
SELECT u.*
FROM users AS u
LEFT JOIN groups AS g ON (g.id NOT IN (u.groups_id))
WHERE u.groups_id = ''
OR g.id IS NULL
mit der JOIN Syntax "ON (g.id NOT IN (u.groups_id))" bin ich mir nicht ganz sicher, ob sie so funktioniert, einfach ausprobieren oder deine JOIN bedingung aus der sucheabfrage nehmen. "kriegsentscheidend" ist der LEFT JOIN und die entsprechende WHERE Klausel mit der OR verknüpgunf beider bedingungen.
Ilja
Hi Ilja,
erstmal danke für Deine Hilfe.
zum einen ist der hinweis von hamster ganz wichtig, nämlich eine dritte beziehungstabelle zu bilden. dann hättest du jetzt erst gar nicht diese probleme.
Na ja. Am Anfang dachte ich mir das auch. Aber dann habe ich mich an Typo3 orientiert, wo die Gruppen auch als kommaseperiete Einträge in das Feld geschrieben werden. Ich dachte, die wissen schon was sie tun ;)
wobei es immer interessant ist, die version deines dbms zu kennen:
MySQL 4.0.20
SELECT u.*
FROM users AS u
LEFT JOIN groups AS g ON (g.id NOT IN (u.groups_id))
WHERE u.groups_id = ''
OR g.id IS NULL
aber nun zu Deiner Abfrage. Sieht im ersten Moment richtig aus, funktioniert aber leider nicht. Es werden noch immer Datensätze ausgegeben, die noch eine vorhandene Gruppe haben. Z.B:
u.groups_id = 264,267,266,268,269,270,271
... und sagen wir mal die Gruppen mit der id 264,271 existieren noch und die Gruppen mit der id 267,266,268,269,270 existieren nicht mehr.
Moment. Jetzt ist mir noch was eingefallen:
SELECT *
FROM users AS u
LEFT JOIN groups AS g ON ( FIND_IN_SET( g.id, u.groups_id ) )
WHERE u.groups_id = '' OR g.id IS NULL
Das funktioniert soweit einmal. Wobei ich es aber nicht verstehen kann. In der LEFT JOIN-Zeile werden doch alle user gesucht, bei denen sich eine g.id im Feld u.groups_id befinden. Im Grunde genommen genau das Gegenteil, von dem was ich will. Und die WHERE-Klausel sucht auch nur ob die Feler leer sind. Aber wo kommt dann die richtige Ausgabe her?
lg lixx
yo,
Aber dann habe ich mich an Typo3 orientiert, wo die Gruppen auch als kommaseperiete Einträge in das Feld geschrieben werden. Ich dachte, die wissen schon was sie tun ;)
keine ahnung, was typo3 so macht. aber du solltest die dritte tabelle mit einbauen. du wirst viele probleme damit los.
Aber wo kommt dann die richtige Ausgabe her?
wie bereits gesagt, über die join bedingung war ich mir nicht ganz sicher. wichtig sind drei dinge, die dir das richtige ergebniss liefern, der left join und die beiden bedingunen in der where klausel.
die erste bedingung (u.groups_id = '') in der where klausel sollte klar sein, nämlich schließe alle datensätze aus, wo der eintrag leer ist, wobei '' etwas anderes ist als NULL.
interessant ist der zweite teil. dort spielen der left join und die zweite bedingung zusammen. er besagt, nimm alle datensatze der user tabelle, wo du keinen eintrag (g.id IS NULL) in der group tabelle findest.
beide bedinungen noch mit or verknüpft und fertig ist die abfrage.
Ilja
interessant ist der zweite teil. dort spielen der left join und die zweite bedingung zusammen. er besagt, nimm alle datensatze der user tabelle, wo du keinen eintrag (g.id IS NULL) in der group tabelle findest.
Ahh! Alles klar. Die NULL-Ausgaben sind mir aufgefallen, und jetzt macht's sinn ;)
lg lixx