2009-07-14 15 views
5

Sto tentando di rilevare valori duplicati/ripetuti all'interno di una tabella gerarchica.Trova righe duplicate/ripetute in sql gerarchico

Si consideri il seguente (un po 'forzata) Esempio:

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; 

Returns ...

 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 

Quello che in realtà voglio è ...

 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 

cioè io voglio ogni riga da restituire tutte le volte che esiste nella sotto-query (ignorando l'ordine). Poiché START WITH utilizza una clausola IN, i valori ripetuti vengono eliminati. È possibile riorganizzare l'SQL in modo che io possa farlo?

Si noti che nel mio caso la sotto-clausola non è UNION, ma è una SELECT che può restituire più valori (possibilmente duplicati) da una tabella.

Potrei farlo in PL/SQL scrivendo i valori in una tabella temporanea e poi GROUPing + COUNTing, ma preferirei farlo in SQL solo se possibile.

Fatemi sapere se è richiesto qualche chiarimento.

Grazie :-)

EDIT:

Nota che ci possono essere 0 ... N valori restituiti dal sub-query.

risposta

-1

è abbastanza facile:

SELECT * FROM empSTART con Mons IN (SELECT empno FROM dip WHERE ename = 'JONES' UNION ALL
SELEZIONA empno FROM dip WHERE ename = 'JONES') CONNECT BY PRIOR empno = mgr;

+0

L'UNION ALL non aiuta .... i valori ripetuti sono surpressed durante la valutazione del IN. – cagcowboy

0

Un modo per duplicare un set di risultati è quello di attraversare join (prodotto cartesiano) ad un set di risultati con due file, vale a dire:

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$ 

Nel tuo caso questo dovrebbe funzionare:

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

provare questo ..

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

direi che questo è il modo tipico di fare questo genere di cose, usando la parola chiave "avere" sql. – djangofan

0

Suona come avete bisogno di abeti Fare un join esterno da emp al risultato della tua query di selezione complessa e quindi basare la query connect-by su quello.

Qualcosa di simile, forse:

 
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;