[英]Query joining null values (left outer join)
继续对帖子提出的要求:
现在我有以下情况:
想法是通过TABLE_A中的输入从TABLE_M中获得组合。
例如。 TABLE_A中的记录1(CODE = 1)对应于COMBINATION1,同时分别通过TABLE_Z和TABLE_X ...
问题出在2、3或4之类的组合中(TABLE_A中的代码)。 这些组合在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;
结果是:
按照预期的结果,我应该能够得到如图所示的图像,但具有正确的组合显示。
哪件事对查询失败?
在那之后,这个想法也将以两种独立的观点出现。
我想一旦我有了正确的查询,我就能轻松地将其拆分。 类似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进入单独的视图来将其拆分为一个视图。 如果我直接拆分查询,我会发现我失去了以前的结果...(我已经拆分了如下查询,以便将T1作为新的VIEW,并且必须像以前一样更改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;
有什么办法可以将其拆分为单独的视图?
由于外部联接条件中的AND
,您实际上无法完全执行您要尝试的操作。 您会部分回到rBarryYoung指出的null等效问题,但是如果您在外部联接(而不是内联视图)中执行null检查,则不会这样做(因为TABLE_X / Z引用都不为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,这是您想要的。
但是由于空值,它分解了。 在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。
我唯一可以看到的视图就是使用子查询分解(也称为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
...但这很可怕,至少与您已有的工作相比。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.