Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Zusätzliche Zeilen erhalten - Nach dem Verbinden der 3 Tabellen mit Left Join

Wenn Sie JOIN werden zwei oder mehr Tabellen zusammen, erhalten Sie effektiv ein kartesisches Produkt für diese Tabellen, zu denen ein Filter im JOIN angegeben ist Bedingung wird angewendet.

Dies wird deutlicher, wenn Sie ein veraltetes implizites JOIN verwenden Syntax.

Der LEFT JOIN garantiert, dass Sie nicht weniger bekommen Zeilen als die Tabelle ganz links enthält, d. e. Jede Zeile der Tabelle ganz links wird mindestens einmal zurückgegeben.

Sie können immer noch mehr Zeilen erhalten, wenn der Filter keine Eins-zu-Eins-Zeilenzuordnung ist.

In Ihrem Fall:

SELECT  (b.descr || ' - ' || c.descr) description
FROM    tbl1 a
LEFT JOIN
        tbl2 b
ON      b.ACCOUNT = a.ACCOUNT
LEFT JOIN
        tbl3 c
ON      c.product = a.product
WHERE  a.descr50 = ' '

entweder acccount oder product sind in b nicht eindeutig oder c .

Für diese Zeilen:

a.account

1
2
3

b.account  b.description

1          Account 1
2          Account 2 - old
2          Account 2 - new

, das JOIN gibt Folgendes zurück:

a.account b.account b.description

1         1          Account 1
2         2          Account 2 - old
2         2          Account 2 - new
3         NULL       NULL

, wodurch Sie mehr Zeilen erhalten, als jede der Tabellen enthält.

Um einfach die erste passende Beschreibung aus einer der Tabellen auszuwählen, verwenden Sie Folgendes:

SELECT  (
        SELECT  FIRST_VALUE(descr) OVER (ORDER BY descr)
        FROM    tbl2 b
        WHERE   b.account = a.account
                AND rownum = 1
        ) || ' - ' ||
        (
        SELECT  FIRST_VALUE(descr) OVER (ORDER BY descr)
        FROM    tbl3 c
        WHERE   c.product= a.product
                AND rownum = 1
        ) description
FROM    tbl1 a
WHERE   a.descr50 = ' '

Zum Aktualisieren packen Sie die Abfrage einfach in eine Inline-Ansicht:

UPDATE  (
        SELECT  (
                SELECT  FIRST_VALUE(descr) OVER (ORDER BY descr)
                FROM    tbl2 b
                WHERE   b.account = a.account
                        AND rownum = 1
                ) || ' - ' ||
                (
                SELECT  FIRST_VALUE(descr) OVER (ORDER BY descr)
                FROM    tbl3 c
                WHERE   c.product= a.product
                        AND rownum = 1
                ) description
        FROM    tbl1 a
        WHERE   a.descr50 = ' '
        )
SET     descr50 = description