5

階層テーブル内の重複/反復値を検出しようとしています。

次の (少し不自然な) 例を考えてみましょう。

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

4 に答える 4

3

これを試してみてください..

SELECT  EMPNO,ENAME FROM,count(*)as counts   emp group by EMPNO,ENAME having count(*)>1
于 2009-07-16T09:17:41.067 に答える
0

最初にempから複雑な選択クエリの結果への外部結合を実行し、次にそれに基づいて接続クエリを実行する必要があるようです。

このようなもの、多分:

mgrs AS(
   SELECT empno FROM emp WHERE ename ='JONES'
   ユニオンオール
   SELECT empno FROM emp WHERE ename ='JONES'
)、
all_emps AS(
   SELECT emp。*、
          mgrs.empnoがNULLでない場合、1 END AS start_with  
   従業員から
   左外側結合mgrsONmgrs.empno = emp.mgr
)。
選択する *
FROM all_emps
START WITH start_with = 1
事前に接続empno=mgr;
于 2009-07-16T14:23:36.050 に答える
0

結果セットを複製する 1 つの方法は、クロス結合 (デカルト積) して 2 行の結果セットにすることです。つまり、次のようになります。

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);
于 2009-07-16T07:49:31.713 に答える
-1

とても簡単です:

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

于 2009-07-14T20:43:22.693 に答える