与join oracle中的子句没有区别

时间:2014-12-23 16:55:48

标签: sql oracle oracle11g distinct

我有一个使用左外连接构造的查询,如下所示:

left outer JOIN GA_LOAN GA 
  ON LOAN.LOAN_TYPE = GA.LOAN_TYP
    AND LOAN.DT = GA.GUARANTY_DT
    AND LOAN.FFEL_DUP_ID = GA.SEP_LOAN_IND
    AND LOAN.SCH_BR_CODE = GA.ORIG_SCHL_CD
    AND STU.CURR_SSN = GA.STU_SSN
    AND STU.DOB = GA.DOB
    and stu.curr_fst = ga.stu_first_nam
  --and (plus_bor.curr_ssn is not distinct from ga.plus_brwr_ssn )

当我添加注释掉的行时,我收到以下错误。

ORA-00908: missing NULL keyword
00908. 00000 -  "missing NULL keyword"
*Cause:    
*Action:

与DB2中此结构中的正常工作没有区别,但Oracle给了我一些问题。有什么建议吗?

如果我将is not distinct from替换为=,但逻辑上不一样,我就没有错误。

如果两个值均为is not distinct from,那么

null会给出匹配,而=在这种情况下不匹配。

2 个答案:

答案 0 :(得分:0)

您可以使用IS DISTINCT FROM结合NOT EXISTS来模仿INTERSECT

plus_bor.curr_ssn IS DISTINCT FROM ga.plus_brwr_ssn
<=>
NOT EXISTS (SELECT plus_bor.curr_ssn FROM dual INTERSECT
            SELECT ga.plus_brwr_ssn FROM dual);

示例:

WITH cte(a,b) AS (
    SELECT 1, NULL    FROM dual UNION ALL
    SELECT 1,2        FROM dual UNION ALL
    SELECT 1,1        FROM dual UNION ALL
    SELECT NULL, 1    FROM dual UNION ALL
    SELECT NULL, NULL FROM dual
)
SELECT *
FROM cte
WHERE NOT EXISTS (SELECT a FROM dual INTERSECT
                SELECT b FROM dual)

<强> Rextester Demo

输出:

A       B
------------
1       NULL
1       2
NULL    1

在您的情况下,IS NOT DISTINCT FROM只是EXISTS

plus_bor.curr_ssn IS NOT DISTINCT FROM ga.plus_brwr_ssn
<=>
EXISTS (SELECT plus_bor.curr_ssn FROM dual INTERSECT
        SELECT ga.plus_brwr_ssn FROM dual);

示例:

WITH cte(a,b) AS (
    SELECT 1, NULL      FROM dual UNION ALL
    SELECT 1,2          FROM dual UNION ALL
    SELECT 1,1          FROM dual UNION ALL
    SELECT NULL, 1      FROM dual UNION ALL
    SELECT NULL, NULL   FROM dual
)
SELECT *
FROM cte
WHERE EXISTS (SELECT a FROM dual INTERSECT
              SELECT b FROM dual);

输出:

 A      B
 1      1
 NULL   NULL

<强> Rextester Demo2

附录

与评论中提出的COALESCE/NVL方法相比,这种方法有一个很大的优势。 您不必考虑依赖于数据类型的默认中性值。

例如,如果列是数据类型DATE / INT / TEXT,那么您必须编写如下内容:

coalesce(col1,DATE '1900-01-01') = coalesce(col2,DATE '1900-01-01')
coalesce(col1, 0) = coalesce(col2, 0)
coalesce(col1, ' ') = coalesce(col2, ' ')

当然有轻微的碰撞机会。例如:

coalesce(col1, 0) = coalesce(col2, 0)
=>
col1 = NULL
col2 = 0
and we have incorrect match!!!

答案 1 :(得分:0)

在 Oracle 中模拟 IS [ NOT ] DISTINCT FROM 的最简单方法是使用 DECODE

-- a IS DISTINCT FROM b
DECODE(a, b, 1, 0) = 0

-- a IS NOT DISTINCT FROM b
DECODE(a, b, 1, 0) = 1

这就是您在使用 jOOQ's SQL dialect translator 时得到的结果。一个 dbfiddle

WITH t (x) AS (
  SELECT 1    FROM dual UNION ALL
  SELECT 2    FROM dual UNION ALL
  SELECT null FROM dual
)
SELECT
  t1.x AS x1,
  t2.x AS x2,
  DECODE(t1.x, t2.x, 1, 0) AS not_distinct
FROM t t1, t t2
ORDER BY 1, 2

产量:

  X1 |   X2 | NOT_DISTINCT
-----+------+-------------
   1 |    1 |            1
   1 |    2 |            0
   1 | null |            0
   2 |    1 |            0
   2 |    2 |            1
   2 | null |            0
null |    1 |            0
null |    2 |            0
null | null |            1