简体   繁体   English

查询联接空值(左外部联接)

[英]Query joining null values (left outer join)

In continuation of what was asked on the post: 继续对帖子提出的要求:

Ora SQL Query: joining without references Ora SQL查询:没有引用的联接

Now I have the following case: 现在我有以下情况:

The idea is to get the combination from TABLE_M by the inputs in TABLE_A. 想法是通过TABLE_A中的输入从TABLE_M中获得组合。

For example. 例如。 The record 1 (CODE = 1) in TABLE_A corresponds to COMBINATION1 while going through TABLE_Z and TABLE_X respectivelly... TABLE_A中的记录1(CODE = 1)对应于COMBINATION1,同时分别通过TABLE_Z和TABLE_X ...

The problem comes with combinations like 2, 3 or 4 (CODE in TABLE_A). 问题出在2、3或4之类的组合中(TABLE_A中的代码)。 These combinations do not have any matching value in TABLE_Z and TABLE_X so then the final result should be something like: 这些组合在TABLE_Z和TABLE_X中没有任何匹配值,因此最终结果应类似于:

  • TABLE_A (code2) ----> COMBINATION 7 TABLE_A(code2)---->组合7
  • TABLE_A (code3) ----> COMBINATION 9 TABLE_A(code3)---->组合9
  • TABLE_A (code4) ----> COMBINATION 8 TABLE_A(code4)---->组合8

I tried to achieve this by using OUTER JOINS but not able to get it succesfully... :( 我试图通过使用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;

And resulting something like: 结果是:

在此处输入图片说明

As per what is expected as result I should be able to get something like shown in picture but with the correct COMBINATION showm. 按照预期的结果,我应该能够得到如图所示的图像,但具有正确的组合显示。

Which thing is failing on the query? 哪件事对查询失败?

After that the idea would be also to have it in two independant views. 在那之后,这个想法也将以两种独立的观点出现。

I guess that once I have the correct query I would be able to split it easilly. 我想一旦我有了正确的查询,我就能轻松地将其拆分。 Something like a CORE_VIEW which would contain TABLE_Z, TABLE_X and TABLE_M and another view which would join TABLE_A and CORE_VIEW. 类似CORE_VIEW的视图,它将包含TABLE_Z,TABLE_X和TABLE_M,而另一个视图将连接TABLE_A和CORE_VIEW。

Then it would be easy for code reusability. 这样就很容易实现代码的可重用性。


After Barry's comment I was able to generate a correct query: 在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));

This is giving me the expected results: 这给了我预期的结果:

在此处输入图片说明

The problem now is that ass said above I need to split it into a view by having TABLE_Z , TABLE_M and TABLE_Y into a sepparate view. 现在的问题是,如上所述,我需要通过让TABLE_Z,TABLE_M和TABLE_Y进入单独的视图来将其拆分为一个视图。 If I directly split the query I see that I loose the results that I was having before... (I have splitted the query like below in order to have T1 as my new VIEW and had to change the order of the JOINS as I was leaving JOINS without ON clause...) 如果我直接拆分查询,我会发现我失去了以前的结果...(我已经拆分了如下查询,以便将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;

在此处输入图片说明

Is there any way I can split it into a sepparate View? 有什么办法可以将其拆分为单独的视图?

You can't really do quite what you're attempting because of the AND in your outer join condition. 由于外部联接条件中的AND ,您实际上无法完全执行您要尝试的操作。 You're partly back to the null equivalence issue rBarryYoung pointed out, but if you do that null check in your outer join, rather than in the inline view (you don't if there as none of your TABLE_X/Z refs are null), you get too many records back. 您会部分回到rBarryYoung指出的null等效问题,但是如果您在外部联接(而不是内联视图)中执行null检查,则不会这样做(因为TABLE_X / Z引用都不为null) ,您将获得太多记录。 This gets 16 rows, the ones you want plus some garbage: 这将获得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));

If you just tried to split out the X_REF values: 如果您只是尝试拆分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

... you'd get 30 rows; ...您将获得30行; and for X_CODE A you have four possible combinations, 1, 3, 5 or 7. For Z_REF it's similar: 对于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

... gets 18 rows; ...获得18行; and for Z_CODE Z you have three possible combinations, 1, 2 and 8. Now, you can compare those two lists and see that for the TABLE_A combination of A and Z the only overlapping combination is number 1, which is what you want. 对于Z_CODE Z,您有三种可能的组合:1、2和8。现在,您可以比较这两个列表,并看到对于A和Z的TABLE_A组合,唯一的重叠组合是数字1,这是您想要的。

But it breaks down because of the nulls. 但是由于空值,它分解了。 In the X_CODE list you get two null matches, for combinations 8 and 9. And in the Z_CODE list you get two null matches, for 7 and 9. Once you add the OR (T1.X_CODE IS NULL) and OR (T1.Z_CODE IS NULL) you get those as well, so for TABLE_A A and Z you get combinations 1 (where both A and Z match), 7 (A matches), 8 (Z matches) and 9 (neither matches). 在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(都不匹配)。

And if you don't have the OR ... IS NULL conditions, you get the right answer when both TABLE_A columns match, but you don't get anything when either column doesn't match, as you saw in the results you included in the question. 而且,如果您没有OR ... IS NULL条件,那么当两个TABLE_A列都匹配时,您会得到正确的答案,但是当任一列都不匹配时,您将不会得到任何结果,如您在包含的结果中所见在这个问题上。 There isn't anything in between. 两者之间没有任何关系。

So you have to drive it from TABLE_A and join to TABLE_M via TABLE_X and TABLE_Z, as you're doing in your 'correct' query. 因此,您必须像在“正确”查询中一样,将其从TABLE_A驱动,并通过TABLE_X和TABLE_Z加入TABLE_M。

The only way I can see you could have that view is to use subquery factoring (aka a CTE) or an actual view, and a union with four branches to handle the possible scenarios: 我唯一可以看到的视图就是使用子查询分解(也称为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);

which does get: 确实得到:

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 

... but that's pretty horrible, at least compared to what you already have working. ...但这很可怕,至少与您已有的工作相比。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM