Peter Nack: Mysql 5, JOIN + IN(), Verstaendnisproblem

Guten Morgen allerseits,

ich sitze nun seit geraumer Zeit an einem Select-Statement, welches ich einfach nicht auf die Reihe bekomme.

Folgendes Szenario:

Tabelle "Auto"

  • Id
  • Name

Tabelle "Ausstattungen"

  • Id
  • Name

(Mapping) Tabelle "Auto_Ausstattungen"

  • Auto_Id
  • Ausstattungen_Id

Nun moechte ich alle Autos auslesen, die zb sowohl eine Klimaanlage als auch eine Sitzheizung haben.

Mein SELECT ist stark vereinfacht wie folgt:

SELECT a.id, a.name  
FROM autos a  
LEFT JOIN ausstattungen AS aus ON a.id = aus.auto_id

Arbeite ich mit der IN()-Anweisung..
mapping.ausstattung_id IN (1,2,3,4)
..so reicht es ja aus, wenn lediglich _eines_ der Ausstattungen zutrifft. Aber nicht alle.
Arbeite ich in der WHERE-Clause zb mit
mapping.ausstattung_id = 4 AND mapping.ausstattung_id = 5
so bekomme ich logishcerweise keine Ergebnisse.

Ich hofffe ich konnte mein Problem verstaendlich genug erlaeutern.
Ein anderer Benutzer hatte das gleiche Problem, und hat dies ein wenig ausfuehrlicher beschrieben.

Ich stehe nach unendlichen Versuchen leider immernoch auf dem Schlauch!
Von daher waere ich fuer jegliche Tips oder Anregungen dankbar!

MfG
Peter

  1. Tach,

    ich habe nun zumindest ein funktionierendes Statement.

    SELECT DISTINCT  
      a.id, a.name  
    FROM  
      auto a  
    WHERE EXISTS (  
      SELECT * FROM Auto_Ausstattung  
      WHERE Auto_Ausstattung.Auto_Id = a.id  
      AND Auto_Ausstattung.Ausstattung_Id =1  
    )  
    AND EXISTS (  
      SELECT * FROM Auto_Ausstattung  
      WHERE Auto_Ausstattung.Auto_Id = a.id  
      AND Auto_Ausstattung.Ausstattung_Id =2  
    )  
    AND EXISTS (  
      SELECT * FROM Auto_Ausstattung  
      WHERE Auto_Ausstattung.Auto_Id = a.id  
      AND Auto_Ausstattung.Ausstattung_Id =3  
    )
    

    Aber das sieht fuer mich ganz schoen brachial aus. Sprich, was, wenn es sich um ein paar Dutzend Ausstattungen handeln sollte? Dann wird es wohl sicherlich starke Performanceprobleme geben.

    MfG
    Peter

  2. Hi,

    (Mapping) Tabelle "Auto_Ausstattungen"

    • Auto_Id
    • Ausstattungen_Id

    Nun moechte ich alle Autos auslesen, die zb sowohl eine Klimaanlage als auch eine Sitzheizung haben.

    Gruppiere die Datensätze der Ausstattungstabelle, deren Ausstattungs-ID Klimaanlage oder Sitzheizung entspricht (WHERE-Klausel), nach der Auto_Id, und verlange, dass die Anzahl der Datensätze in dieser Gruppierung zweien entspricht (HAVING, COUNT()).

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    1. Hallo Chris,

      danke fuer deinen Beitrag!

      Auch wenn ich, zugegeben, von HAVING und GROUP BY nicht gerade viel Ahnung habe, konnte ich mir nun anhand deiner Erklaerung folgendes Statement zusammen basteln:

      SELECT DISTINCT  
      	a.name, aus.name  
      FROM  
      	auto a  
      LEFT JOIN  
      	auto_ausstattung aa ON a.id = aa.auto_id  
      LEFT JOIN  
      	ausstattung aus ON aa.ausstattung_id = aus.id  
      WHERE  
      	 aus.id = 1 OR aus.id = 2 OR aus.id = 3  
      GROUP BY  
      	a.id  
      HAVING  
      	COUNT(aa.ausstattung_id) = 3
      

      Gibt es hieran etwas auszusetzen oder kann ich das so verwenden?
      Die Ergebnisse scheinen korrekt zu sein.

      MfG
      Peter

      1. Hallo,

        anhand der bisherigen Ratschlaege konnte ich das Problem des von mir initial beschriebenen Falles loesen, doch stehe ich nun leider wieder vor einem Problem, an dem ich nicht weiter komme.

        Und zwar ist die Situation wie folgt - vergessen wir mal mein bisheriges Beispiel:

        Die Datenstruktur ist wie folgt aufgebaut:

        • Resort
            - n ResortFacilites
            - n Rooms
              - n RoomFacilities

        Der Benutzer kann die Filteroptionen setzen fuer
        a) die Facilities eines Resorts und
        b) die Facilities des Rooms einse Resorts

        Anwendungsfall:
        Ich moechte alle Resorts mit "Loundry Service" und "Car Rental" (resort_facilities), sowie nur Zimmer, welche "Klimaanlage" und "Internet" besitzen (room_facilities).

        Lassen wir die RoomFacilities einmal aussen vor, so funktioniert folgendes (vereinfachtes) Statement fuer die ResortFacilities:

          
        SELECT DISTINCT SQL_CALC_FOUND_ROWS  
        	resort.id, resort.name, resort.location_id	  
        FROM  
        	resort 	  
        LEFT JOIN  
        	mm_resort_facility ON resort.id = mm_resort_facility.resort_id  
        LEFT JOIN  
        	resort_facility ON mm_resort_facility.resort_facility_id = resort_facility.id  
        -- LEFT JOIN  
            -- room ON resort.id = room.resort_id  
        --  -- LEFT JOIN  
        	-- -- mm_room_facility ON room.id = mm_room_facility.room_id  
        -- -- LEFT JOIN  
        	-- -- room_facility ON mm_room_facility.room_facility_id = resort_facility.id  
        WHERE  
        	( resort_facility.id=1 OR resort_facility.id=2 OR resort_facility.id=3 )  
        GROUP BY  
        	resort.id  
        HAVING  
        	COUNT(mm_resort_facility.resort_facility_id) = 3  
        ORDER BY  
        	votes_overall  
        DESC  LIMIT 0, 4  
        
        

        == Problem 1 ==
        Kommentiere ich hingegen jedoch die durch "--" auskommentierten Zeilen wieder ein (nicht die doppelt auskommentierten), so bekomme ich ein falsches Ergebnis (falsch heisst in diesem Kontext, dass nicht alle Resorts korrekt zurueckgegeben werden).

        == Problem 2 (Ausbaustufe) ==
        Nun kommen die RoomFacilties noch zusaetzlich mit ins Spiel.
        Und an dieser Stelle stehe ich derzeit vor einem riesigen Fragezeichen.
        Denn an dieser Stelle geht ja das ganze GroupBy und Having-Handling in die Knie. Und der JOIN (unter Problem 1 beschrieben) scheitert ja auch schon.

        Was fuer Moeglichkeiten habe ich, meine Anforderungen in einem einzigen Statement unterzubringen?
        Gibt es da eine schicke und auch performante Loesung

        MfG
        Peter, der sehr dankbar waere, wenn einer der SQL-Experten mir hier einen Tip geben koennte.

        PS: Ich kann auch gerne noch einen Datenbank-Dump liefern.