繁体   English   中英

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

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

继续对帖子提出的要求:

Ora SQL查询:没有引用的联接

现在我有以下情况:

想法是通过TABLE_A中的输入从TABLE_M中获得组合。

例如。 TABLE_A中的记录1(CODE = 1)对应于COMBINATION1,同时分别通过TABLE_Z和TABLE_X ...

问题出在2、3或4之类的组合中(TABLE_A中的代码)。 这些组合在TABLE_Z和TABLE_X中没有任何匹配值,因此最终结果应类似于:

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

我试图通过使用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.

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