获得额外的行 - 使用Left Join连接3个表后

时间:2009-07-29 11:55:46

标签: sql oracle

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

table1只有7622行descr50 ='',但是这个选择返回7649行。你能帮帮我吗?提前谢谢

3 个答案:

答案 0 :(得分:4)

当您JOIN两个或多个表格在一起时,您可以有效地获取这些表格的笛卡尔积,并在JOIN条件中应用过滤器。

当您使用过时的隐式JOIN语法时,这一点更为明显。

LEFT JOIN保证你得到的行比最左边的表包含的行,i。即最左边的表中的每一行至少返回一次。

如果过滤器不是一对一的行映射,您仍然可以获得更多行。

在你的情况下:

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 = ' '

acccountproductbc中不是唯一的。

对于这些行:

a.account

1
2
3

b.account  b.description

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

JOIN将返回以下内容:

a.account b.account b.description

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

,为您提供比任何一个表所包含的行更多的行。

要从任一表中选择第一个匹配的描述,请使用:

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 = ' '

要更新,只需将查询包装到内联视图中:

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

答案 1 :(得分:3)

table1可能只有7622行,但如果tbl2具有多个具有相同ACCOUNT值的行,或者如果tbl3具有多个产品匹配的行,则结果集中将获得更多行。你有效地“乘以”每个表。


编辑:好的,一个例子。

假设tbl1只有1行,并且“ACCOUNT”为1而“product”为2.(我不知道表中的实际值是什么;无关紧要。)

现在假设tbl2有2行,其中“ACCOUNT”为1.直接,您将在结果中获得至少2行,因为tbl1将匹配tbl2中的2行。

现在,如果tbl3有2行,其中“product”为2,则结果中会得到 4 行,因为上面的2个结果中的每一个都会匹配tbl3中的2行。

所以希望你能看到为什么你获得的行数超出预期。您选择做什么是另一回事,取决于tbl2和tbl3中是否存在多个匹配这一事实表明数据存在问题。

答案 2 :(得分:1)

作为确定其他行来自何处​​的测试,请尝试从连接表中向SELECT语句添加更多字段,并查看返回的数据。

纠正问题的一个选项是在加入表后对其进行分组:

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

另一个选择是在加入tbl2和tbl3表之前对它们进行分组:

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