继续对帖子提出的要求:
Ora SQL Query: joining without references
现在我有以下情况:
我们的想法是通过TABLE_A中的输入从TABLE_M中获取组合。
例如。 TABLE_A中的记录1(CODE = 1)对应于COMBINATION1,同时分别通过TABLE_Z和TABLE_X ...
问题来自于2,3或4之类的组合(TABLE_A中的CODE)。这些组合在TABLE_Z和TABLE_X中没有任何匹配值,因此最终结果应该是这样的:
我试图通过使用OUTER JOINS来实现这一目标,但却无法成功实现...... :(
SELECT A.REF_X,A.REF_Z, X.CODE,Z.CODE,M.DESCR
FROM TABLE_A A
LEFT OUTER JOIN TABLE_Z Z
ON A.REF_Z = Z.CODE
LEFT OUTER JOIN TABLE_X X
ON A.REF_X = X.CODE
LEFT OUTER JOIN TABLE_M M
ON Z.REF1 = M.Z_REF1
AND Z.REF2 = M.Z_REF2
AND Z.REF3 = M.Z_REF3
AND X.REF1=M.X_REF1;
结果如下:
根据预期的结果,我应该能够获得如图所示的东西,但是使用了正确的COMBINATION showm。
查询失败的是什么?
之后,我们的想法也是将它放在两个独立的视图中。
我想,一旦我有了正确的查询,我就可以轻松地将其拆分。类似CORE_VIEW的东西,包含TABLE_Z,TABLE_X和TABLE_M,另一个视图将连接TABLE_A和CORE_VIEW。
然后,代码可重用性会很容易。
在Barry的评论之后,我能够生成正确的查询:
SELECT A.REF_X,A.REF_Z, X.CODE,Z.CODE,M.DESCR
FROM TABLE_A A
LEFT OUTER JOIN TABLE_Z Z
ON A.REF_Z = Z.CODE
LEFT OUTER JOIN TABLE_X X
ON A.REF_X = X.CODE
LEFT OUTER JOIN TABLE_M M
ON (Z.REF1 = M.Z_REF1 OR (Z.REF1 IS NULL AND M.Z_REF1 IS NULL))
AND (Z.REF2 = M.Z_REF2 OR (Z.REF2 IS NULL AND M.Z_REF2 IS NULL))
AND (Z.REF3 = M.Z_REF3 OR (Z.REF3 IS NULL AND M.Z_REF3 IS NULL))
AND (X.REF1 = M.X_REF1 OR (X.REF1 IS NULL AND M.X_REF1 IS NULL));
这给了我预期的结果:
现在的问题是上面说的我需要将TABLE_Z,TABLE_M和TABLE_Y分成一个sepparate视图,将它拆分成一个视图。 如果我直接拆分查询,我看到我放弃了之前的结果...(我已经拆分了下面的查询,以便将T1作为我的新视图,并且必须改变JOINS的顺序,因为我是离开JOINS没有ON子句......)
SELECT A.REF_X,A.REF_Z, T1.X_CODE, T1.Z_CODE, T1.DESCR
FROM TABLE_A A
LEFT OUTER JOIN
(SELECT X.CODE X_CODE,Z.CODE Z_CODE,M.DESCR
FROM TABLE_Z Z
LEFT OUTER JOIN TABLE_M M
ON (Z.REF1 = M.Z_REF1 OR (Z.REF1 IS NULL AND M.Z_REF1 IS NULL))
AND (Z.REF2 = M.Z_REF2 OR (Z.REF2 IS NULL AND M.Z_REF2 IS NULL))
AND (Z.REF3 = M.Z_REF3 OR (Z.REF3 IS NULL AND M.Z_REF3 IS NULL))
LEFT OUTER JOIN TABLE_X X
ON (X.REF1 = M.X_REF1 OR (X.REF1 IS NULL AND M.X_REF1 IS NULL))
) T1
ON A.REF_X = T1.X_CODE
AND A.REF_Z = T1.Z_CODE;
有什么方法可以将它拆分成一个sepparate View吗?
答案 0 :(得分:2)
由于外部连接条件中的AND
,您无法真正完成所尝试的操作。你部分回到了rBarryYoung所指出的null等价问题,但如果你这样做,则检查你的外连接,而不是内联视图(如果没有,你的TABLE_X / Z refs都不为null) ,你得到的记录太多了。这会得到16行,你想要的那些加上一些垃圾:
SELECT A.REF_X, A.REF_Z, T1.X_CODE, T1.Z_CODE, T1.DESCR
FROM TABLE_A A
LEFT JOIN (
SELECT X.CODE X_CODE,Z.CODE Z_CODE,M.DESCR
FROM TABLE_M M
LEFT JOIN TABLE_Z Z
ON Z.REF1 = M.Z_REF1
AND Z.REF2 = M.Z_REF2
AND Z.REF3 = M.Z_REF3
LEFT JOIN TABLE_X X
ON X.REF1 = M.X_REF1
) T1
ON (T1.X_CODE = A.REF_X OR (T1.X_CODE IS NULL))
AND (T1.Z_CODE = A.REF_Z OR (T1.Z_CODE IS NULL));
如果您只是尝试拆分X_REF值:
SELECT M.CODE M_CODE, X.CODE X_CODE, M.DESCR
FROM TABLE_M M
LEFT JOIN TABLE_X X
ON X.REF1 = M.X_REF1
...你会得到30排;对于X_CODE A,您有四种可能的组合,1,3,5或7.对于Z_REF,它类似:
SELECT M.CODE M_CODE, Z.CODE Z_CODE, M.DESCR
FROM TABLE_M M
LEFT JOIN TABLE_Z Z
ON Z.REF1 = M.Z_REF1
AND Z.REF2 = M.Z_REF2
AND Z.REF3 = M.Z_REF3
......获得18行;对于Z_CODE Z,你有三种可能的组合,1,2和8.现在,你可以比较这两个列表,看看对于A和Z的TABLE_A组合,唯一重叠的组合是数字1,这就是你想要的。 / p>
但是因为空值而崩溃了。在X_CODE列表中,对于组合8和9,您将获得两个空匹配。在Z_CODE列表中,您将获得两个空匹配,分别为7和9.一旦添加OR (T1.X_CODE IS NULL)
和OR (T1.Z_CODE IS NULL)
,您将获得这些匹配同样,对于TABLE_A A和Z,你得到组合1(其中A和Z匹配),7(A匹配),8(Z匹配)和9(不匹配)。
如果您没有OR ... IS NULL
条件,那么当两个TABLE_A列匹配时,您会得到正确的答案,但是当任何一列不匹配时您没有得到任何结果,正如您在结果中看到的那样你包括在这个问题中。中间没有任何东西。
所以你必须从TABLE_A驱动它并通过TABLE_X和TABLE_Z加入TABLE_M,正如你在'正确'的查询中所做的那样。
我能看到你的唯一方法就是使用子查询因子分析(a.k.a a CTE)或实际视图,以及带有四个分支的联合来处理可能的场景:
WITH T1 AS (
SELECT X.CODE X_CODE,Z.CODE Z_CODE,M.DESCR
FROM TABLE_M M
LEFT JOIN TABLE_Z Z
ON Z.REF1 = M.Z_REF1
AND Z.REF2 = M.Z_REF2
AND Z.REF3 = M.Z_REF3
LEFT JOIN TABLE_X X
ON X.REF1 = M.X_REF1
)
SELECT A.REF_X, A.REF_Z, T1.X_CODE, T1.Z_CODE, T1.DESCR
FROM TABLE_A A
JOIN T1 ON T1.X_CODE = A.REF_X AND T1.Z_CODE = A.REF_Z
UNION ALL
SELECT A.REF_X, A.REF_Z, T1.X_CODE, T1.Z_CODE, T1.DESCR
FROM TABLE_A A
JOIN T1 ON T1.X_CODE = A.REF_X AND T1.Z_CODE IS NULL
WHERE NOT EXISTS (SELECT 1 FROM T1 WHERE Z_CODE = A.REF_Z)
UNION ALL
SELECT A.REF_X, A.REF_Z, T1.X_CODE, T1.Z_CODE, T1.DESCR
FROM TABLE_A A
JOIN T1 ON T1.Z_CODE = A.REF_Z AND T1.X_CODE IS NULL
WHERE NOT EXISTS (SELECT 1 FROM T1 WHERE X_CODE = A.REF_X)
UNION ALL
SELECT A.REF_X, A.REF_Z, T1.X_CODE, T1.Z_CODE, T1.DESCR
FROM TABLE_A A
JOIN T1 ON T1.Z_CODE IS NULL AND T1.X_CODE IS NULL
WHERE NOT EXISTS (SELECT 1 FROM T1 WHERE X_CODE = A.REF_X OR Z_CODE = A.REF_Z);
确实得到:
REF_X REF_Z X_CODE Z_CODE DESCR
----- ----- ------ ------ ------------
A Z A Z COMBINATION1
C Y C Y COMBINATION4
D U D U COMBINATION3
F W F W COMBINATION6
A FFF A COMBINATION7
TTT T T COMBINATION8
SSS JJJ COMBINATION9
......但这非常可怕,至少与你已经工作过的相比。