Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Obtendo linhas extras - Depois de ingressar nas 3 tabelas usando o Left Join


Quando você JOIN duas ou mais tabelas juntas, você obtém efetivamente um produto cartesiano para essas tabelas para as quais um filtro declarado no JOIN condição é aplicada.

Isso é mais óbvio quando você usa um JOIN implícito obsoleto sintaxe.

O LEFT JOIN garante que você não receba menos linhas do que a tabela mais à esquerda contém, i. e. cada linha da tabela mais à esquerda é retornada pelo menos uma vez.

Você ainda pode obter mais linhas, se o filtro não for um mapeamento de linha um para um.

No seu caso:
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 = ' '

ou acccount ou product não são únicos em b ou c .

Para estas linhas:
a.account

1
2
3

b.account  b.description

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

, o JOIN retornará o seguinte:
a.account b.account b.description

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

, fornecendo mais linhas do que qualquer uma das tabelas contém.

Para escolher apenas a primeira descrição correspondente de qualquer tabela, use isto:
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 = ' '

Para atualizar, basta envolver a consulta em uma visualização inline:
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