2

DBテーブルのいくつかの行を更新する必要があります。更新する行を特定する方法には、一連の複雑なステートメントが含まれ、それらを一連のWITHステートメントにまとめることができました。これで正しいデータ値が得られたので、テーブルを更新する必要があります。

WITHステートメントでこれらの値を取得できたので、UPDATE/MERGEで使用したいと思っていました。簡単な例は次のとおりです。

with data1
(
    ID_1
)
as
(
    Select ID
    from  ID_TABLE
    where ID > 10
)
,
cmedb.data2
(
     MIN_ORIGINAL_ID
    ,OTHER_ID
)
as
(
    Select min(ORIGINAL_ID)
           ,OTHER_ID
    from   OTHER_ID_TABLE
    where  OTHER_ID in
    (
        Select distinct ID_1
        From   data1
    )
    group by OTHER_ID

)
select MIN_ORIGINAL_ID
      ,OTHER_ID
from cmedb.data2

これで2列のデータができたので、それらを使用してテーブルを更新します。そのため、下部にselectを表示する代わりに、UPDATE / MERGEの上にWITHステートメントを配置したり、UPDATE / MERGEステートメントの一部として使用したりするなど、マージと更新のあらゆる種類の組み合わせを試しました。以下は、私がやりたいことに最も近いものです。

merge into ID_TABLE as it
using
(
    select MIN_ORIGINAL_ID
          ,OTHER_ID
    from cmedb.data2

) AS SEL
ON
(
    it.ID = sel.OTHER_ID
)
when matched then
update
set it.ORIGINAL_ID = sel.MIN_ORIGINAL_ID

だからそれは動作しません。UPDATEまたはMERGEと組み合わせてWITHステートメントを使用した例がインターネット上で見つからなかったため、これが可能かどうかはわかりません。INSERTと組み合わせて使用​​されているWITHステートメントの例があるので、それが可能であると信じています。

誰かが助けてくれるならそれは素晴らしいことです、そして私が問題を解決するのに役立つであろう情報を省略したかどうか私に知らせてください。

免責事項:私が提供した例は、私がやろうとしていることの要約版であり、実際には意味がないかもしれません!

4

6 に答える 6

4

@Andrew Whiteが言うように、MERGEステートメントで一般的なテーブル式を使用することはできません。

ただし、ネストされた副選択を使用して、一般的なテーブル式を削除できます。ネストされた副選択を使用して書き直されたselectステートメントの例を次に示します。

select min_original_id, other_id
from (
   select min(original_id), other_id
   from   other_id_table
   where  other_id in (
      select distinct id_1 from (select id from id_table where id > 10) AS DATA1 (ID_1)
   )
   group by other_id
) AS T (MIN_ORIGINAL_ID, OTHER_ID);

これはやや複雑です(正確なステートメントはより適切に記述できます)が、単純化された例を示しているだけであることがわかります。

一般的なテーブル式の代わりにネストされた副選択を使用して、MERGEステートメントを書き直すことができる場合があります。それは確かに構文的に可能です。

例えば:

merge into other_id_table x
using (
   select min_original_id, other_id
   from (
      select min(original_id), other_id
      from   other_id_table
      where  other_id in (
         select distinct id_1 from (select id from id_table where id > 10) AS DATA1 (ID_1)
      )
      group by other_id
   ) AS T (MIN_ORIGINAL_ID, OTHER_ID)
) as y
on y.other_id = x.other_id
when matched 
   then update set other_id = y.min_original_id;

繰り返しますが、これは複雑ですが、少なくとも可能であることを示しています。

于 2011-02-01T17:38:55.333 に答える
2

UPDATE(およびINSERTも)でWITHステートメントを使用する方法は、 SELECT FROM UPDATEステートメント(ここ)を使用することです。

WITH TEMP_TABLE AS (
    SELECT [...]
)
SELECT * FROM FINAL TABLE (
    UPDATE TABLE_A SET (COL1, COL2) = (SELECT [...] FROM TEMP_TABLE)
    WHERE [...]
);
于 2018-02-23T19:24:11.883 に答える
1

私は今文法を調べていますが、答えはノーだと確信しています。少なくとも、私が最後に使用したバージョンのDB2ではそうではありません。更新を確認し、ドキュメントページをマージして構文を確認してください。構文にfullselectが表示されている場合でも、 select docページwithに従って明示的に分離されているため、使用できません。

于 2011-02-01T15:29:02.510 に答える
1

DB2 V8以降を実行している場合は、ここに興味深いSQLハックがあり、WITHステートメントを使用してクエリを更新/挿入できます。多くの予備的なデータ準備を必要とする挿入と更新の場合、この方法は非常に明確であることがわかります。

ここで1つの修正を編集します-UPDATEステートメントからの選択はV9で導入されたと思います。したがって、上記はV8以降の挿入、およびV9以降の更新で機能します。

于 2012-02-03T15:15:11.333 に答える
1

CTEをビューに配置し、マージのビューから選択します。そのようにして、クリーンで読みやすいビューと、クリーンで読みやすいマージが得られます。

于 2017-10-10T14:06:38.657 に答える
0

もう1つの方法は、WITHクエリを単純に置き換えて、副選択を使用することです。

たとえば、次のような場合(そして、より現実的な世界を示すために、WHEREロジック、集計関数(MAX)、およびGROUP BYを含むやや複雑な例を含めようとしました):

WITH
  Q1 AS (
    SELECT
      A.X,
      A.Y,
      A.Z,
      MAX(A.W) AS W
    FROM
      TABLEB B
      INNER JOIN TABLEA A ON B.X = A.X AND B.Y = A.Y AND B.Z = A.Z
    WHERE A.W <= DATE('2013-01-01') 
    GROUP BY
      A.X,
      A.Y,
      A.Z
  ),

  Q2 AS (
    SELECT
      A.X,
      A.Y,
      A.Z,
      A.W,
      MAX(A.V) AS V
    FROM
      Q1
      INNER JOIN TABLEA A ON Q1.X = A.X AND Q1.Y = A.Y AND Q1.Z = A.Z AND Q1.W = A.W
    GROUP BY
      A.X,
      A.Y,
      A.Z,
      A.W
  )

SELECT
  B.U,
  A.T
FROM
  Q2
  INNER JOIN TABLEA A ON Q2.X = A.X AND Q2.Y = A.Y AND Q2.Z = A.Z AND Q2.W = A.W AND Q2.V = A.V)
  RIGHT OUTER JOIN TABLEB B ON Q2.X = B.X AND Q2.Y = B.Y AND Q2.Z = B.Z

...次のようにすることで、これをMERGEINTOに適したものに変えることができます。

  1. 上部のWITHを削除します
  2. Q1ブロックの最後からコンマを削除します(閉じ括弧の後)
  3. 開始括弧の前からQ1ASを取得し、終了括弧の後に配置して(コンマを削除)、Q1の前にASを配置します。
  4. この新しいQ1ブロックを取得し、それを切り取って、FROM Q1の後にQ2ブロックに貼り付けます(Q1をクリップボードのクエリに置き換えます)注:もちろん、Q1への他の参照(内部結合キー内)はそのままにしておきます。
  5. これで、より大きなQ2クエリができました。手順3と4をもう一度実行します。今回は、メイン選択のQ2(FROMの後)をクリップボードのより大きなQ2クエリに置き換えます。

最終的には、次のような単純なSELECTクエリが作成されます(適切なインデントを表示するように再フォーマットされています)。

SELECT
  B.U,
  A.T
FROM
  (SELECT
     A.X,
     A.Y,
     A.Z,
     A.W,
     MAX(A.V) AS V
   FROM
     (SELECT
        A.X,
        A.Y,
        A.Z,
        MAX(A.W) AS W
      FROM
        TABLEB B
        INNER JOIN TABLEA A ON B.X = A.X AND B.Y = A.Y AND B.Z = A.Z
      WHERE A.W <= DATE('2013-01-01') 
      GROUP BY
        A.X,
        A.Y,
        A.Z) AS Q1
     INNER JOIN TABLEA A ON Q1.X = A.X AND Q1.Y = A.Y AND Q1.Z = A.Z AND Q1.W = A.W
     GROUP BY
       A.X,
       A.Y,
       A.Z,
       A.W) AS Q2
INNER JOIN TABLEA A ON Q2.X = A.X AND Q2.Y = A.Y AND Q2.Z = A.Z AND Q2.W = A.W AND Q2.V = A.V
RIGHT OUTER JOIN TABLEB B ON Q2.X = B.X AND Q2.Y = B.Y AND Q2.Z = B.Z

私はこれを私自身の個人的な経験(ちょうど今実際に)で行いました、そしてそれは完全に機能します。

幸運を。

于 2013-06-28T14:53:48.767 に答える