在分层sql中查找重复/重复的行

时间:2009-07-14 20:41:48

标签: sql oracle hierarchical-data

我正在尝试检测分层表中的重复/重复值。

考虑以下(稍作设想)的例子:

SELECT *
FROM   emp
START WITH mgr IN (SELECT empno FROM emp WHERE ename = 'JONES'
                   UNION ALL
                   SELECT empno FROM emp WHERE ename = 'JONES')
CONNECT BY PRIOR empno = mgr;

...返回

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
      7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
      7902 FORD       ANALYST         7566 03-DEC-81       3000                    20
      7369 SMITH      CLERK           7902 17-DEC-80        800                    20

我真正想要的是......

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
      7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
      7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
      7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
      7369 SMITH      CLERK           7902 17-DEC-80        800                    20
      7369 SMITH      CLERK           7902 17-DEC-80        800                    20
      7902 FORD       ANALYST         7566 03-DEC-81       3000                    20
      7902 FORD       ANALYST         7566 03-DEC-81       3000                    20

即我希望每行返回的次数与子查询中存在的次数相同(忽略顺序)。由于START WITH使用IN子句,因此重复的值被抑制。是否可以重新组织SQL以便我可以这样做?

请注意,在我的情况下,子句不是UNION,而是一个SELECT,它可以从表中返回多个(可能是重复的)值。

我可以在PL / SQL中通过将值写入临时表然后进行GROUPing + COUNTing来实现,但我希望只在可能的情况下在SQL中执行此操作。

如果需要澄清,请告诉我。

谢谢: - )

编辑:

请注意,子查询可能会返回0 ... N个值。

4 个答案:

答案 0 :(得分:3)

试试这个..

SELECT  EMPNO,ENAME FROM,count(*)as counts   emp group by EMPNO,ENAME having count(*)>1

答案 1 :(得分:0)

复制结果集的一种方法是将连接(笛卡儿积)交叉到具有两行的结果集,即:

SQL> WITH your_query AS (
  2     SELECT object_name
  3       FROM all_objects WHERE ROWNUM <= 3
  4  )
  5  SELECT your_query.*
  6    FROM your_query
  7   CROSS JOIN (SELECT NULL FROM dual UNION ALL SELECT NULL FROM dual);

OBJECT_NAME
------------------------------
IND$
IND$
ICOL$
ICOL$
OBJ$
OBJ$

在你的情况下,这应该有效:

WITH your_query AS (
   SELECT *
     FROM emp
    START WITH mgr IN (SELECT empno FROM emp WHERE ename = 'JONES')
          CONNECT BY PRIOR empno = mgr
)
SELECT your_query.*
  FROM your_query
 CROSS JOIN (SELECT NULL FROM dual UNION ALL SELECT NULL FROM dual);

答案 2 :(得分:0)

听起来你需要首先从emp到你的复杂选择查询的结果进行外部联接,然后根据它进行连接查询。

像这样的东西,也许:

WITH mgrs AS (
   SELECT empno FROM emp WHERE ename = 'JONES'
   UNION ALL
   SELECT empno FROM emp WHERE ename = 'JONES'
),
all_emps AS (
   SELECT emp.*, 
          CASE WHEN mgrs.empno IS NOT NULL THEN 1 END AS start_with  
   FROM emp
   LEFT OUTER JOIN mgrs ON mgrs.empno = emp.mgr
)
SELECT *
FROM all_emps
START WITH start_with = 1
CONNECT BY PRIOR empno = mgr;

答案 3 :(得分:-1)

这很容易:

  

SELECT * FROM     empstART with mgr IN   (SELECT empno FROM emp WHERE ename =   '琼斯'联盟所有人   SELECT empno FROM emp WHERE ename =   'JONES')先前连接empno = mgr;