Flo: Mehrere Werte in einer Spalte finden

Hallo zusammen,

ich habe folgende Tabelle namens "tags":

ID|tag
+++++++++
1|hund
2|katze
1|maus
3|pferd

Wenn ich nun in der Spalte "tag" nach "hund" und "maus" suche möchte ich als Ergebnis die ID 1 bekommen, da "hund" und "maus" eben nur bei ID 1 vorkommt.

Ich schicke folgendes Statement an MySQL:

SELECT *
FROM tags
WHERE tag = 'hund' AND tag = 'maus'

Aber ich bekomme leider kein Ergebnis (0). Ersetze ich AND durch OR kommt es zum einen Ergebnis. Ich möchte allerdings nicht die ID haben  wo "hund" oder "maus" vorkommt, sondern eben nur die ID wenn beide Wörter bei der selben ID kommt.

Danke für die Antwort

Flo

  1. Hallo!

    SELECT *
    FROM tags
    WHERE tag = 'hund' AND tag = 'maus'

    Was spricht gegen OR?

    SELECT * FROM tags WHERE tag = 'hund' OR tag = 'maus'

    André Laugks

    --
    Die Frau geht, die Hilti bleibt!
    1. n'abend,

      Was spricht gegen OR?
      SELECT * FROM tags WHERE tag = 'hund' OR tag = 'maus'

      Dagegen spricht vorrangig, dass du mit dieser Anfrage alle Datensätze bekommst, bei denen Tag _entweder_ der Wert 'hund' _oder_ 'maus' ist.

      Hätte man die folgende Tabelle:

      id | tag
       1 | hund
       2 | vogel
       2 | hund
       1 | maus
       3 | katze

      wäre das Ergebnis deiner Anfrage:

      id | tag
       1 | hund
       2 | hund
       1 | maus

      gewollt ist aber

      id
       1

      weiterhin schönen abend...

      --
      Freundlich wie man war, hat man mir Großbuchstaben geschenkt.
      sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
  2. Hallo Florian

    ID|tag
    +++++++++
    1|hund
    2|katze
    1|maus
    3|pferd

    Ich möchte allerdings nicht die ID haben  wo "hund" oder "maus" vorkommt, sondern eben nur die ID wenn beide Wörter bei der selben ID kommt.

    auf die Schnelle wäre der Einsatz des Selfjoin ein funktionierender Weg:

      
    SELECT t1.ID  
    FROM tags t1  
    INNER JOIN tags t2   -- Verknüpfe die Tabelle mit sich selbst über die ID  
    ON t1.ID = t2.ID     -- Nur Werte mit gleicher ID werden einander zugeordnet  
    WHERE                           -- Nimm nur die Kombinationen  
        t1.tag = 'Hund'             -- bei der in der ersten Tabelle 'Hund'  
        AND t2.tag = 'Maus'
    ~~~  -- und in der zweiten 'Maus' steht  
      
      
    Freundliche Grüße  
      
    Vinzenz
    
  3. n'abend,

    Wenn ich nun in der Spalte "tag" nach "hund" und "maus" suche möchte ich als Ergebnis die ID 1 bekommen, da "hund" und "maus" eben nur bei ID 1 vorkommt.

    Da gibt es wohl mehrere Möglichkeiten diese Aufgabenstellung zu lösen. Es kommt aber drauf an welches DBMS in welcher Version du benutzt. Nicht alle Datenbanken können mit allen Anfragearten umgehen.

    Ich schicke folgendes Statement an MySQL:

    Und welche MySQL-Version?

    SELECT *
    FROM tags
    WHERE tag = 'hund' AND tag = 'maus'

    Dass das *niemals* überhaupt auch nur einen einzigen Datensatz finden kann, ist dir klar, oder? Ähnlich wie ein (unifarbenes) Auto exakt eine Farbe hat, hat ein Datenfeld auch nur einen einzigen Wert. Wieviele einfarbige Autos findest du denn, wenn du nur Autos haben möchtest, die rot und grün sind? richtig! Das geht gar nicht, da wir ja vorher festgestellt haben, dass ein Auto einfarbig ist, also exakt _eine_ Farbe hat. Genau das ist auch bei deinem Datenfeld der Fall.

    Aber ich bekomme leider kein Ergebnis (0). Ersetze ich AND durch OR kommt es zum einen Ergebnis. Ich möchte allerdings nicht die ID haben  wo "hund" oder "maus" vorkommt, sondern eben nur die ID wenn beide Wörter bei der selben ID kommt.

    Das einfachste (und zugleich schlechteste) Beispiel, das mir einfällt, welches auf jedem Datenbanksystem gleichermaßen laufen sollte ist das Kartesische Produkt der Tabelle bilden:

    SELECT a.id  
    FROM deineTabelle a,  
         deineTabelle b  
    WHERE a.tag = 'Hund'  
      AND b.tag = 'Maus';
    

    Dieses Vorgehen ist für große Datenmengen und oder eine hohe Anzahl Abfragen jedoch wirklich *nicht* empfehlenswert.

    Benutzt du MySQL 4.1 (oder höher), stehen dir SubQueries (verschachtelte Anfragen) zur Verfügung. Dann könntest du etwas wie das folgende basteln:

    SELECT id  
    FROM deineTabelle  
    WHERE tag = 'Hund'  
      AND id IN (  
        SELECT id  
        FROM deineTabelle  
        WHERE tag = 'Maus'  
      );
    

    Die Subquery-Variante hat den Vorteil, dass sie um ein vielfaches schneller verarbeitet werden kann, als die "Kartesisches Produkt"-Variante. Allerdings ist diese Anfrage auch nur dann brauchbar, wenn du nicht mehr als 2 gleichzeitige Werte abfragen möchtest.

    Möchtest du unbegrenzt viele Werte abfragen können, ist ein Beispiel wie das folgende denkbar:

    SELECT id  
    FROM deineTabelle  
    WHERE tag IN ('Hund', 'Katze', 'Maus', 'Marsupilami')  
    GROUP BY id  
    HAVING COUNT(*) = 4;
    

    Wobei die Zahl 4 in der letzten Zeile die Anzahl der möglichen Werte von tag sein muss.

    (Natürlich sind diese Anfragen nicht getestet...)

    weiterhin schönen abend...

    --
    Freundlich wie man war, hat man mir Großbuchstaben geschenkt.
    sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
  4. Hallo zusammen,

    erstmal vielen Dank für die Antwort.

    Vielleicht noch kurz zum Hintergrund meiner Frage. Ich habe Projekte denen ich Tags zuordne.

    Wenn ich nun nach Tags suchen möchte soll es natürlich auch möglich sein nach Projekten mit mehren Tags zu suchen. Wie in meinem Beispiel suche ich das Projekt mit "hund" und "maus".

    Ich habe folgende Tabellen:

    Tags: tagID, tagWord
    Projects: projectID, projectName
    tags_projects: tags_projectID, projectID, tagID

    Ich werden Eure Vorschläge morgen durcharbeiten aber evtl. gibts ja grundsätzlich einen anderen Lösungsweg der sinnvoller ist.

    Danke

    Flo

    1. n'abend,

      Wenn ich nun nach Tags suchen möchte soll es natürlich auch möglich sein nach Projekten mit mehren Tags zu suchen. Wie in meinem Beispiel suche ich das Projekt mit "hund" und "maus".

      Da mir bislang keiner der Datenbanken-Gurus widersprochen hat, empfehle ich die letzte Query aus meinen Beispielen.

      weiterhin schönen abend...

      --
      Freundlich wie man war, hat man mir Großbuchstaben geschenkt.
      sh:( fo:# ch:# rl:| br:> n4:& ie:{ mo:} va:) de:] zu:} fl:( ss:? ls:[ js:|
  5. hi,

    SELECT *
    FROM tags
    WHERE tag = 'hund' AND tag = 'maus'

    Aber ich bekomme leider kein Ergebnis (0).

    Wieso leider?
    Deine Datenbank wäre kaputt, falls das ein anderes Ergebnis geben würde.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. hi,

      SELECT *
      FROM tags
      WHERE tag = 'hund' AND tag = 'maus'

      Aber ich bekomme leider kein Ergebnis (0).

      Wieso leider?
      Deine Datenbank wäre kaputt, falls das ein anderes Ergebnis geben würde.

      gruß,
      wahsaga

      Ja schon ;-), aber es kommt nicht das was ich möchte. Aber ich weiß schon, liegt immer am Anwender... ;-)