2009-07-14 5 views
5

Я пытаюсь обнаружить дублированные/повторяющиеся значения в иерархической таблице.Найти повторяющиеся/повторяющиеся строки в иерархическом sql

Рассмотрим следующий (немного надуманный) пример:

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, записав значения в таблицу temp, а затем GROUPING + COUNTING, но я бы предпочел сделать это только в SQL, если это возможно.

Дайте мне знать, если требуются какие-либо разъяснения.

Спасибо :-)

EDIT:

Обратите внимание, что там может быть 0 ... N возвращаемые значения из подзапроса.

ответ

-1

это довольно легко:

SELECT * FROM empSTART С Дисп В (SELECT EMPNO FROM EMP WHERE ENAME = 'JONES' UNION ALL
ВЫБРАТЬ EMPNO FROM EMP WHERE ENAME = 'JONES') CONNECT BY PRIOR empno = mgr;

+0

СОЮЗ ALL не помогает .... повторяющиеся значения surpressed при оценке IN. – cagcowboy

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); 
3

Попробуйте один ..

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

Я бы сказал, что это типичный способ делать такие вещи, используя «наличие» ключевого слова sql. – djangofan

0

Похоже, что вам нужно пихты t выполните внешнее соединение с 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; 
Смежные вопросы