Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Abfrage mit Left Join und Self Join

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von MajorHOB, 16 Juli 2013.

  1. MajorHOB

    MajorHOB Neuer Benutzer

    Hallo ich versuche mich gerade an einer Abfrage mit mehreren Tabellen und einem Self Join.
    Ich möchte gerne das jede Spalte aus der Tabelle product genau einmal vorkommt.
    aidfeat soll entweder 1 oder NULL sein.
    bidfeat soll entweder 2 oder NULL sein.

    Folgenden SQL Code hab ich verwendet:
    Code:
    SELECT product.id_product, reference, status, a.id_feature aidfeat, a.id_feature_value aval,  b.id_feature bidfeat, b.id_feature_value bval
    FROM product
    LEFT JOIN pcupdate ON product.reference = pcupdate.artikelnummer
    LEFT JOIN feature_product a ON product.id_product = a.id_product
    LEFT JOIN feature_product b ON product.id_product = b.id_product
    WHERE (a.id_feature=1 OR a.id_feature IS NULL)
    
    und das ist das Ergebniss:

    Code:
     id_product | reference  | status | aidfeat | aval | bidfeat | bval
    ------------+------------+--------+---------+------+---------+-----
     100        | 19100      | 1      | 1       | 1    | 1       | 1 
     100        | 19100      | 1      | 1       | 1    | 2       | 2
     101        | 1103       | 2      | 1       | 2    | 1       | 2
     102        | 19050      | 2      | NULL    | NULL | NULL    | NULL
     103        | 19100      | 1      | NULL    | NULL | NULL    | NULL
     104        | sdfds      | NULL   | NULL    | NULL | NULL    | NULL
    
    schon nicht schlecht wie ich finde jetzt nur noch die Bedingung für bidfeat eingeben um die erste Zeile auszublenden und in der 3.Zeile bei ID 101 aus bidfeat und bval ein NULL zu zaubern.
    Dafür verwede ich folgenden Code:
    Code:
    SELECT product.id_product, reference, status, a.id_feature aidfeat, a.id_feature_value aval,  b.id_feature bidfeat, b.id_feature_value bval
    FROM product
    LEFT JOIN pcupdate ON product.reference = pcupdate.artikelnummer
    LEFT JOIN feature_product a ON product.id_product = a.id_product
    LEFT JOIN feature_product b ON product.id_product = b.id_product
    WHERE (a.id_feature=1 OR a.id_feature IS NULL)
    AND
    (b.id_feature=2 OR b.id_feature IS NULL)
    
    und das ist das Ergebnis:

    Code:
     id_product | reference  | status | aidfeat | aval | bidfeat | bval
    ------------+------------+--------+---------+------+---------+-----
     100        | 19100      | 1      | 1       | 1    | 2       | 2
     102        | 19050      | 2      | NULL    | NULL | NULL    | NULL
     103        | 19100      | 1      | NULL    | NULL | NULL    | NULL
     104        | sdfds      | NULL   | NULL    | NULL | NULL    | NULL
    
    leider schmeißt mir die Abfrage jetzt die ID 101 komplett raus. Welche WHERE Bedingung kann ich verwenden.
    Vielen Dank und schönen Abend.
     
  2. akretschmer

    akretschmer Datenbank-Guru


    Zeig bitte, was in den Tabellen steht (mach ne kurze Demo) und was rauskommen soll. Und formatiere es so, daß man es ordentlich sieht.
     
  3. MajorHOB

    MajorHOB Neuer Benutzer

    Ok ich hab es im ersten Beitrag mal etwas leserlicher gemacht
    Hier folgen meine Tabellen. Ich habe sie nochmal um einen Fall (id 999) erweitert, der auch noch Auftreten kann.

    Code:
     Tabelle "product"
     
     id_product | reference  
    ------------+------------
     100        | 19100      
     101        | 1103       
     102        | 19050      
     103        | 19100      
     104        | sdfds      
     999        | 99999
    
    Code:
    Tabelle "pcupdate"
     
     artikelnummer | Status 
    ---------------+------------
     1103          | 2      
     19050         | 2       
     19100         | 1      
     19500         | 2      
     18888         | 1
    
    Code:
     Tabelle "feature_product"
     
     id_feature | id_product | id_feature_value 
    ------------+------------+-----------------
     1          | 100        | 1     
     1          | 101        | 2      
     2          | 100        | 2     
     2          | 999        | 1    
    
    und das sollte bei der Abfrage rauskommen

    Code:
     id_product | reference  | status | aidfeat | aval | bidfeat | bval
    ------------+------------+--------+---------+------+---------+-----
     100        | 19100      | 1      | 1       | 1    | 2       | 2
     101        | 1103       | 2      | 1       | 2    | NULL    | NULL
     102        | 19050      | 2      | NULL    | NULL | NULL    | NULL
     103        | 19100      | 1      | NULL    | NULL | NULL    | NULL
     104        | sdfds      | NULL   | NULL    | NULL | NULL    | NULL
     999        | 18888      | 1      | NULL    | NULL | 2       | 1  
    
     
  4. akretschmer

    akretschmer Datenbank-Guru


    Aufgrund massiver Knotenbildung in /dev/brain geb ich auf. Dein doppelter JOIN auf feature_product führt zu einem versteckten cross join. Ich raff Deine Logig nicht und nicht, was das Ziel sein soll. Sorry.
     
  5. ukulele

    ukulele Datenbank-Guru

    Also dieser Code tut was er soll:
    Code:
    SELECT product.id_product, reference, status, a.id_feature aidfeat, a.id_feature_value aval,  b.id_feature bidfeat, b.id_feature_value bval
    FROM product
    LEFT JOIN pcupdate ON product.reference = pcupdate.artikelnummer
    LEFT JOIN feature_product a ON product.id_product = a.id_product
    LEFT JOIN feature_product b ON product.id_product = b.id_product
    WHERE (a.id_feature=1 OR a.id_feature IS NULL)
    AND
    (b.id_feature=2 OR b.id_feature IS NULL)
    ...er schmeist alle Werte raus bei denen deine Bedingungen zutreffen:
    Dir fehlt diese Zeile:
    Code:
      id_product | reference  | status | aidfeat | aval | bidfeat | bval
    ------------+------------+--------+---------+------+---------+-----
    101        | 1103      | 2      | 1      | 2    | NULL    | NULL
    ...die aber so gar nicht existiert nur:
    Code:
     id_product | reference  | status | aidfeat | aval | bidfeat | bval
    ------------+------------+--------+---------+------+---------+-----
     101        | 1103       | 2      | 1       | 2    | 1       | 2
    ... existiert wenn man sich deinen ersten Select anschaut. Du möchtest also nicht das die Ergebnisse ausgeschlossen werden wie es in der WHERE Bedingung gemacht wird sondern das sie abgeändert werden!

    So müsstest du zum Ziel kommen. Ich mach das jetzt mal beispielhaft für den einen Datensatz und nur bidfeat, ich kenne ja nicht alle möglichen Kombinationen und Werte die auftreten können und weiss nicht, wie sie abgeändert werden sollen. Ich Gucke ob der Wert 2 oder NULL ist andernfalls ändere ich den Wert auf NULL ab.:
    Code:
    SELECT    product.id_product,
            reference,
            status,
            a.id_feature AS aidfeat,
            a.id_feature_value AS aval,
            (    CASE
                WHEN    b.id_feature = 2
                OR        b.id_feature IS NULL
                THEN    b.id_feature
                ELSE    NULL
                END ) AS bidfeat,
            b.id_feature_value AS bval
    FROM    product
    LEFT JOIN pcupdate ON product.reference = pcupdate.artikelnummer
    LEFT JOIN feature_product a ON product.id_product = a.id_product
    LEFT JOIN feature_product b ON product.id_product = b.id_product
    WHERE (    a.id_feature = 1
    OR        a.id_feature IS NULL )
     
    MajorHOB gefällt das.
  6. MajorHOB

    MajorHOB Neuer Benutzer

    Super ukulele :)

    Ich habs zwar noch nicht ausprobiert, aber das sieht richtig gut aus.

    Mir ist ein richtiges Licht aufgegangen. Klar wenn ich keine Zeile habe, die meiner gesuchten entspricht, wie soll ich sie dann mit where rausfiltern.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden