内部连接相同的查询 returns 比单独执行时多结果

Inner joined same query returns more result than when it's executed alone

我不知道我是否错了,但我一直认为(现在仍然如此)记录的数量 return 是通过单独查询 table 和内部连接得到的相同的 table 和查询此关系将是相同的。像这样:

select 'foo' foo from dual;

对比

select * from (select 'foo' foo from dual)q1 inner join
(select 'foo' foo from dual)q2
 on q1.foo=q2.foo

这两个查询 return 一条记录。但是我有一个查询,当我在内部将它与自身连接时,我得到了更多的记录。这是我的查询:

SELECT distinct DOC.DOCID
FROM AG_INW_DOC DOC
JOIN LAG_CITIZENS CIT
ON DOC.CITIZENID=CIT.CITIZENID
JOIN
  (SELECT TSK.DOCID,
    OFCR.DEPID
  FROM AG_TASKS TSK
  JOIN AG_TASK_EXECUTORS EXEC
  ON TSK.TASKID=EXEC.TASKID
  JOIN AG_OFFICERS OFCR
  ON EXEC.ISSUEDOFFICERID   =OFCR.OFFICERID
  WHERE EXEC.ISMAINEXECUTOR =1

  )TSK ON DOC.DOCID         =TSK.DOCID
LEFT JOIN
  (SELECT ESCDOCID, UNDERCONTROL,ORGID FROM AG_ESCORTING_DOCUMENTS
  ) ESC
ON DOC.ESCDOCID       =ESC.ESCDOCID
WHERE DOC.CATEGORYID IN (11,12)
AND TRUNC(DOC.RECEIVEDDATE,'DDD') BETWEEN TO_DATE('01.11.2015') AND TO_DATE('30.11.2015')
AND (TSK.DEPID      IN ('017','004')
OR (TSK.DEPID        ='008'
AND DOC.SUBJECTID   IN (1,2,3,4,20,22,23,24) ))
AND DOC.DOCSTAT!     =3

UNION ALL
SELECT distinct  DOC.DOCID
FROM AG_INW_DOC DOC
JOIN LAG_CITIZENS CIT
ON DOC.CITIZENID=CIT.CITIZENID
LEFT JOIN AG_TASKS TSK
ON DOC.DOCID =TSK.DOCID
LEFT JOIN
  (SELECT ESCDOCID, UNDERCONTROL,ORGID FROM AG_ESCORTING_DOCUMENTS
  ) ESC
ON DOC.ESCDOCID             =ESC.ESCDOCID
WHERE DOC.CATEGORYID       IN (11,12)
AND DOC.ADDRESSEDOFFICERID IN (9,26)
AND TRUNC(DOC.RECEIVEDDATE,'DDD') BETWEEN TO_DATE('01.11.2015') AND TO_DATE('30.11.2015')
AND DOC.DOCSTAT!          =3

如果我单独 运行 这个查询,我会得到 3019 条记录 returned。但是如果我 inner join 它本身和 select 从这个连接我得到 3023 条记录。

现在,我不希望有人检查我的查询并指出问题所在。我只需要知道什么情况可能会导致这种行为。

编辑

查询 return 只有不同的值。无重复

你的假设是错误的。

内部联接会将第一个 select 的每个结果与第二个 select 的每个结果组合起来,然后过滤联接条件。因此,如果您的 select returns 具有以下三个值的单个列:

1, 2, 2

与自身的连接以及值必须相同的连接条件将产生

所以你得到 5 行而不是 3 行。

如果不查看您的实际 select,您的连接条件的列中可能有非唯一值。

(1, 1), (2, 2), (2, 2), (2, 2), (2, 2)

为了找到重复项,您可以像这样完成查询

select DOCID, count(*) from (
-- your query here
) group by DOCID
having count(*) > 1

仅当您加入主键或唯一键时,您的假设才成立。

这里有一个小例子来说明相反的情况:

此查询给出了两行,但键不是唯一的:

select 'foo, I''M no PK' foo from dual union all  
select 'foo, I''M no PK' foo from dual
;

连接上面的行源(使用 WITH)给出 2 * 2 行。

with dual2 as (
select 'foo, I''M no PK' foo from dual union all  
select 'foo, I''M no PK' foo from dual
)
select * from (select   foo from dual2)q1 inner join
(select   foo from dual2)q2
 on q1.foo=q2.foo
 ;

.

foo, I'M no PK  foo, I'M no PK
foo, I'M no PK  foo, I'M no PK
foo, I'M no PK  foo, I'M no PK
foo, I'M no PK  foo, I'M no PK

更新

以上假设成立,但与本题无关。

问题出在构造上DISTINCT UNION ALL DISTINCT

这可能会出现错误 - 必须改用 UNION

例子

with tab1 as ( 
select 1 foo  from dual union all  
select 1 foo  from dual union all
select 2 foo  from dual)
, tab2 as (
select 2 foo  from dual union all  
select 2 foo  from dual union all
select 3 foo  from dual)

select DISTINCT foo from tab1
UNION ALL
select DISTINCT foo from tab2
order by 1;

给予

1
2
2
3