2009-07-14 94 views
5

Tôi đang cố gắng phát hiện các giá trị trùng lặp/lặp lại trong bảng phân cấp.Tìm hàng trùng lặp/lặp lại trong phân cấp sql

xem xét như sau (hơi giả tạo) ví dụ:

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 

Những gì tôi thực sự muốn là ...

 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 

tức là tôi muốn mỗi hàng được trả về nhiều lần khi nó tồn tại trong truy vấn phụ (bỏ qua thứ tự). Vì START WITH đang sử dụng mệnh đề IN, các giá trị lặp lại đang bị loại bỏ. Có thể tổ chức lại SQL để tôi có thể làm điều này không?

Lưu ý rằng trong trường hợp của tôi mệnh đề phụ không phải là một UNION, nhưng là một SELECT có thể trả về nhiều giá trị (có thể trùng lặp) từ một bảng.

Tôi có thể làm điều đó trong PL/SQL bằng cách viết các giá trị vào bảng tạm thời và sau đó GROUPing + COUNTing, nhưng tôi muốn làm điều đó trong SQL chỉ khi có thể.

Hãy cho tôi biết nếu cần làm rõ.

Cảm ơn :-)

EDIT:

Lưu ý rằng có thể có 0 ... N giá trị trở về từ các tiểu truy vấn.

Trả lời

-1

nó khá dễ dàng:

SELECT * FROM empSTART VỚI mgr TRÊN (SELECT empno FROM emp ĐÂU ename = 'JONES' UNION ALL
CHỌN empno FROM emp ĐÂU ename = 'JONES') CONNECT BY PRIOR empno = mgr;

+0

Các UNION ALL không giúp .... các giá trị lặp đi lặp lại được surpressed trong việc thẩm định IN. – cagcowboy

0

Một cách để lặp lại một tập kết quả là phải vượt qua tham gia (sản phẩm Descartes) nó vào một kết quả thiết lập với hai hàng, ví dụ:

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$ 

Trong trường hợp của bạn này nên làm việc:

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

Hãy thử một trong này ..

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

Tôi muốn nói đây là cách điển hình để thực hiện loại điều này, sử dụng từ khóa "có" sql. – djangofan

0

Âm thanh như bạn cần phải linh sam t làm một tham gia bên ngoài từ emp đến kết quả của truy vấn lựa chọn phức tạp của bạn, và sau đó căn cứ truy vấn kết nối theo đó.

Something như thế này, có lẽ:

 
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; 
Các vấn đề liên quan