1

相関サブクエリを使用しようとしているのに、Oracle のネスト制限に達している状況があります。オラクルが持つ別の機能が欠けている可能性があるため、この質問をここに投稿すると思いました。このネストの制限に達せずに以下の SQL を書き直す方法を知っている人はいますか?また、以下の制約内に留まりますか?

制約:

  • IN 句の SQL のみを変更できます(制御できない制約のため)
  • 示されているように、集計が発生する前に、親クエリのフィルタリングを集計サブクエリに適用する必要があります。
  • 親フィルターが適用された後、colB の集計で 0 を除外します

以下のコードは、Oracle の制限に達する前にこれを試したことを示しています。また、私が使用している Oracle のバージョンは 11.2.0.2 です。どんな助けでも大歓迎です。ありがとう!

SELECT
  *
FROM
  table1 t1
WHERE
  t1.colA BETWEEN XXXX AND XXXX 
  AND t1.pk_id IN (
    SELECT
      t2.pk_id
    FROM (
      SELECT
        t3.pk_id,
        SUM(t3.amt) OVER (PARTITION BY t3.colB) amt
      FROM table1 t3
        WHERE t3.colA = t1.colA
    ) t2
    WHERE
      t2.amt <> 0
  )

上記の SQL を実行するときに探していたもののサンプル入力/出力を次に示します。

Sample table1:
-----------------------------
| pk_id | colA | colB | amt |
-----------------------------
|   1   |  1   |  A   |  2  |
|   2   |  1   |  A   |  -1 |
|   3   |  1   |  B   |  1  |
|   4   |  2   |  B   |  1  |
|   5   |  2   |  A   |  -2 |
|   6   |  2   |  A   |  1  |
|   7   |  3   |  A   |  1  |

t1.colA BETWEEN 1 And 2 を使用した t3.colB の SUM の結果:

---------------
| pk_id | amt |
---------------
|   1   |  0  |
|   2   |  0  |
|   3   |  2  |
|   4   |  2  |
|   5   |  0  |
|   6   |  0  |    

t1.colA BETWEEN 1 And 2 を使用した IN 句のサブクエリの結果:

---------
| pk_id |
--------- 
|   3   |
|   4   |

t1.colA BETWEEN 1 And 2 を使用した最上位クエリの結果:

-----------------------------
| pk_id | colA | colB | amt |
-----------------------------
|   3   |  1   |  B   |  1  |
|   4   |  2   |  B   |  1  |

提供された回答のいくつかに取り組んだ後、単純な CASE ステートメントを使用して、Oracle のネスト制限を回避する方法を見つけました。

SELECT
  *
FROM
  table1 t1
WHERE
  t1.colA BETWEEN 1 AND 2
  AND t1.pk_id IN (
    SELECT
      CASE
        WHEN SUM(t2.amt) OVER (PARTITION BY t2.colB) <> 0 THEN t2.pk_id
        ELSE NULL
      END
    FROM table1 t2
    WHERE t2.colA = t1.colA
  )

残念ながら、これにより本当の問題が表面化しました。これはサブクエリであるため、一度に t1.colA 範囲の 1 つの値のみを反復処理できます。これにより、サブクエリでその範囲内の分析合計を実行できなくなっているようです。IN 句内の SQL しか変更できないため、この問題の解決策がわかりません。誰か提案があれば教えてください。ありがとう。

4

2 に答える 2

0

間の値が何であるかを知っていて、サブクエリでそれらを使用できる場合は、代わりにそれをサブクエリに追加できます。

SELECT
    *
FROM
    table1 t1
WHERE
    t1.colA BETWEEN 1 AND 2
    AND t1.pk_id IN (
        SELECT
            t2.pk_id
        FROM 
            (
                SELECT
                    t3.pk_id,
                    SUM(t3.amt) OVER (PARTITION BY t3.colB) amt
                FROM table1 t3
                WHERE t3.colA BETWEEN 1 AND 2
            ) t2
        WHERE
            t2.amt <> 0
    )

SQL フィドルのデモ

于 2013-05-24T00:39:05.707 に答える
0

次のようにクエリを書き直すことができます。

SELECT *
FROM table1 t1
WHERE t1.colA BETWEEN XXXX AND XXXX and
      t1.pk_id IN (
        SELECT t2.pk_id
        FROM (SELECT t3.pk_id, t3.ColA, SUM(t3.amt) as amt
              FROM table1 t3
              group by t3.pk_id, t3.ColA
              having sum(t3.amt) > 0
             ) t2
        WHERE t2.colA = t1.colA
      )

ここから、次のように書き換えることができます。

select t1.*
from table1 t1 join
     (SELECT t3.pk_id, t3.ColA, SUM(t3.amt) as amt
      FROM table1 t3
      group by t3.pk_id, t3.ColA
      having sum(t3.amt) > 0
     ) t2
     on t1.pk_id = t2.pk_id and t1.ColA = t3.ColA
WHERE t1.colA BETWEEN XXXX AND XXXX 
于 2013-05-24T03:01:04.257 に答える