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行。你能帮帮我吗?提前谢谢
答案 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 = ' '
acccount
或product
在b
或c
中不是唯一的。
对于这些行:
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 = ' '