Kalle_Worms: UND- Bedingung als Aufzähltyp ?

Hallöle,

habe eine Tabelle mit Produkten (Handys), eine mit Merkmalen und eine dritte, die Produkte und Merkmale zuordnet:

id | artikel_id | merkmal_id

Nun möchte ich alle Produkte finden, die das Merkmal 63 (E-Mail-Client)  UND das Merkmal 64 (Sprachaufzeichnung) UND, UND, UND haben.

SELECT artikel_id FROM ... WHERE merkmal_id = 63 AND merkmal_id = 64 AND ...

Ist etwas umständlich. Wenn ich mit ODER suchen würde, könnte ich ja die Aufzählung WHERE merkmal_id IN ( 63, 64, ... ) nehmen.

Gibt es für UND einen entsprechenden Aufzählungstyp ?

LG Kalle

  1. SELECT artikel_id FROM ... WHERE merkmal_id = 63 AND merkmal_id = 64 AND ...

    merkmal_id kann nicht gleichzeitig 63 und 64 sein. Ich nehme an, daß du für das Feld merkmal\_id den Typ SET verwendest, die MySQL Docu schlägt da folgende Syntax vor:
    mysql> SELECT * FROM tabelle WHERE set_spalte = 'wert1,wert2';

    http://dev.mysql.com/doc/mysql/de/SET.html

    Grüße

    Heizer

    1. SELECT artikel_id FROM ... WHERE merkmal_id = 63 AND merkmal_id = 64 AND ...

      merkmal_id kann nicht gleichzeitig 63 und 64 sein.

      Ja, da hast du recht. Ich merke gerade, dass ich einen Fehler in der Konzeption der Abfrage habe.

      Also, die Tabelle sieht so aus:

      artikel_id | merkmal_id
      -----------+-------------
      4711       ! 62
      4711       ! 63
      4711       ! 64
      4711       ! 99
      4712       ! 15
      4712       ! 63
      4712       ! 64
      4713       ! 63
      4713       ! 78

      Nun möchte ich die artikel_id, die sowohl das Merkmal 63, als auch das Merkmal 64 hat. Antwort muss sein: 4711, 4712.

      Wie bekomme ich das jetzt hin ***grübel***

      Kalle

      1. Hallo Kalle_Worms,

        SELECT artikel_id FROM ... WHERE merkmal_id = 63 AND merkmal_id = 64 AND ...

        merkmal_id kann nicht gleichzeitig 63 und 64 sein.

        es sei denn merkmal_id kommt zweimal vor, aus zwei Tabellen.

        artikel_id | merkmal_id
        -----------+-------------
        4711       ! 62
        4711       ! 63
        4711       ! 64
        4711       ! 99
        4712       ! 15
        4712       ! 63
        4712       ! 64
        4713       ! 63
        4713       ! 78

        Sieht nach einem Selfjoin aus:

        SELECT a.artikel_id
        FROM tabelle AS a
        INNER JOIN tabelle as b ON a.artikel_id = b.artikel_id
        WHERE a.merkmal_id = 63 AND b.merkmal_id = 64

        sollte das gewünschte Ergebnis liefern.

        Freundliche Grüsse,

        Vinzenz

        1. Hallo Vinzenz,

          Sieht nach einem Selfjoin aus:

          SELECT a.artikel_id
          FROM tabelle AS a
          INNER JOIN tabelle as b ON a.artikel_id = b.artikel_id
          WHERE a.merkmal_id = 63 AND b.merkmal_id = 64

          sollte das gewünschte Ergebnis liefern.

          Danke dir. Pro zusätzlicher Bedingung kommt immer ein JOIN hinzu?

          Ich glaube, diese Lösung ist mit PHP einfacher per for- Schleife zu generieren:

          SELECT amk.artikel_id id, COUNT( * ) anz_mrk
          FROM bia_artikel_merkmale amk
          WHERE amk.masz <> 'n'
          AND (
          amk.merkmal_id =45
          OR amk.merkmal_id =1
          OR amk.merkmal_id =53
          OR amk.merkmal_id =2
          )
          GROUP BY amk.artikel_id
          HAVING COUNT( * ) =4

          Als ich die Frage stellte, wusste ich nicht, dass man GROUP BY mit COUNT kombinieren und mit HAVING weiter einschränken kann.

          Kalle

          1. yo,

            Danke dir. Pro zusätzlicher Bedingung kommt immer ein JOIN hinzu?

            genau, deswegen ist der SELF JOIN in diesem falle nicht besonders gut geeignet, weil er sich schlecht erweitern läßt. da ist dein weg über GROUP BY schon ein guter. allerdings setzt er vorraus, dass die beiden id's zusammen einen PK bilden, da es sonst probleme mit dem COUNT(*) geben kann. aber das sollte sicherlich der fall sein.

            ine kleine ergänzung noch, die OR bedingunen lassen sich besser zusammenfassen.

            WHERE amk.masz <> 'n' AND amk.merkmal_id IN (45, 1, 53, 2)

            Als ich die Frage stellte, wusste ich nicht, dass man GROUP BY mit COUNT kombinieren und mit HAVING weiter einschränken kann.

            nun HAVING ist genau dafür gemacht worden, gruppierungen weiter einzuschränken. und da HAVING er ganz am "schluss" angewandt wird, lassen sich auch hier aggregat-funktionen einsetzten.

            Ilja

      2. Hallöle,

        bin der Lösung schon näher gekommen.

        Mit der folgenden Abfrage sehe ich unter anz_mrk, WIE VIELE Treffer pro artikel_id gefunden wurden. Es sind 1, 2 oder 3.

        Ich möchte nur die artikel_id mit ALLEN 3 Treffern. Wie funzt das? Da muss dem GROUP BY doch noch was angehängt werden?

        SELECT amk.artikel_id id, COUNT( * ) anz_mrk
        FROM bia_artikel_merkmale amk
        WHERE amk.masz <> 'n'
        AND (
        amk.merkmal_id =45
        OR amk.merkmal_id =14
        OR amk.merkmal_id =39
        )
        GROUP BY amk.artikel_id

        Kalle