- PR -

値の更新

1
投稿者投稿内容
なし
会議室デビュー日: 2004/09/17
投稿数: 17
投稿日時: 2004-10-22 17:35
お世話になっています。

テーブル
┌─┬─┬─┬─┬─┐
│ Q│ A│ B│ C│ D│
├─┼─┼─┼─┼─┤
│ X│ 1│ a│ b│ @│ @=a+b
├─┼─┼─┼─┼─┤
│ X│ 2│ c│ d│ A│ A=@+c+d
├─┼─┼─┼─┼─┤
│ X│ 3│ e│ f│ B│ B=A+e+f
├─┼─┼─┼─┼─┤
    :
├─┼─┼─┼─┼─┤
│ X│ X│ y│ z│ n│ n=(n−1)+y+z
└─┴─┴─┴─┴─┘

上図のような処理をSQLでやりたいのですが、

Aをキーとして、A-1のレコードのD列の値を別のテーブルに作成
処理が成功した時
Aをキーとして、Aのレコードに(Bの値)+(Cの値)+(上で作成したテーブルのDの値)をD列に書き込む

という処理を1つのSQLで作成しています。
この処理をAのレコード数分処理して、途中経過の合計と最終結果の合計をD列に書き込みたいのですがうまくいきません。

尚、データはQ列をキーに数セットもあります。

何かよい方法はないものでしょうか?
ご教授の程よろしくお願い致します。

[ メッセージ編集済み 編集者: ハヤセ 編集日時 2004-10-22 17:36 ]
tak3
ベテラン
会議室デビュー日: 2004/04/15
投稿数: 80
お住まい・勤務地: 菜の花・銀杏
投稿日時: 2004-10-23 00:51
やりたいことは、よくわかったのですが、何がうまくいかないのかわかりません。
カラムBとカラムCの合計のやりかたではないですよね?
SQLが多数発行されるのがイヤなのでしょうか?

QがPK、Aがソート順(UNIQUE)と思っていいですかね。
引用:

n=(n−1)+y+z


上記の計算は、「n= SUM(B) + SUM(C)」と等価ですよね?

とすると
引用:

│ X│ 2│ c│ d│ (2)│ 


の場合

(2) = SUM(B) + SUM(C) WHERE A <= 2 とすれば、
N回のUPDATEで問題ないと思います。

1回のUPDATEでやる方法もありますが、メモリとか食いそうなので
この方法がいいかなと思います。(わかりやすいですし)
# 集計関数をばかばか呼ぶのもあまり良くないかもしれませんが・・・

# 丸数字は(数字)置き換えました。
なし
会議室デビュー日: 2004/09/17
投稿数: 17
投稿日時: 2004-10-25 09:25
お返事ありがとうございます

やりたいことがわかってもらえてよかったです^^
これじゃ、わかりにくいかな?とか思いながらもドキドキでした

引用:

QがPK、Aがソート順(UNIQUE)と思っていいですかね。
引用:

n=(n−1)+y+z


上記の計算は、「n= SUM(B) + SUM(C)」と等価ですよね?

とすると
引用:

│ X│ 2│ c│ d│ (2)│ 


の場合

(2) = SUM(B) + SUM(C) WHERE A <= 2 とすれば、
N回のUPDATEで問題ないと思います。



tak3さんがおっしゃる通りの計算になります。
私がうまくいかないのは、2回目の計算以降のUPDATEです。
と言っても、今回はINSERTを使用しました。

A=2の時、A=1のDを参照するクエリを作成して

D(A=2)=SUM(D(A=1))+SUM(B(A=2))+SUM(C(A=2)) をINSERT

A=3の時、A=2のDを参照するクエリを作成して

D(A=3)=SUM(D(A=2))+SUM(B(A=3))+SUM(C(A=3)) をINSERT

 :

といったような方法を取った時、
A=2の時のSUM(D(A=1))と、A=3の時のSUM(D(A=2))…が取得できませんでした。
(たぶん、クエリの性質上、無理なのでは?と思います。)



でも、tak3さんがおっしゃった

引用:

(2) = SUM(B) + SUM(C) WHERE A <= 2 とすれば、
N回のUPDATEで問題ないと思います。



を見ると、無理に前回の値を参照する式を作らなくても
簡単に算出できるじゃないか…と気が付きました。

スゴイ変なことしてたと、つくづく思います…

tak3さんの方法でやってみます。
ありがとうございました。



[ メッセージ編集済み 編集者: ハヤセ 編集日時 2004-10-25 09:27 ]
なし
会議室デビュー日: 2004/09/17
投稿数: 17
投稿日時: 2004-10-25 10:28
tak3さんの方法でやるとうまくいきました。

目先の計算値のことだけ考えており、
値の本質を忘れていました…

改めてありがとうございました。m(_ _)m
tak3
ベテラン
会議室デビュー日: 2004/04/15
投稿数: 80
お住まい・勤務地: 菜の花・銀杏
投稿日時: 2004-10-25 10:42
INSERT時にD値のデータを作れるなら、わざわざSUMを使わなくてもできると思いますよ。
あのUPDATE文をN回実行するのは正直抵抗がありました。

で、以下の前提条件があります。
・Aは欠番無しの連番(UNIQUE)になっていること。

---テーブルHOGE---
Q CHAR(2)
A NUMBER(2)
B NUMBER(2)
C NUMBER(2)
D NUMBER(3)
-------

コード:
INSERT INTO HOGE VALUES('AA', 1, 1, 2, NVL((SELECT D FROM HOGE WHERE A = 1 - 1), 0)+1+2);
INSERT INTO HOGE VALUES('BB', 2, 3, 4, NVL((SELECT D FROM HOGE WHERE A = 2 - 1), 0)+3+4);
INSERT INTO HOGE VALUES('CC', 3, 5, 6, NVL((SELECT D FROM HOGE WHERE A = 3 - 1), 0)+5+6);

---結果---
Q           A          B          C          D
-- ---------- ---------- ---------- ----------
AA          1          1          2          3
BB          2          3          4         10
CC          3          5          6         21


以下余計な説明です。
VALUES句の先頭から4つは特に問題無いと思います。
次の部分「NVL(...)+b値+c値」がDカラムにINSERTされる値になります。
A=1の時、A=0(A=1-1)のDをSELECTして、INSERTするA(1),B(2)を加算したものをDの値とします。
以下同様

NVLはSELECT結果がNULLの場合を0とするためにいれています。
実行すれば確認できると思いますが、
INSERT INTO HOGE VALUES('01', '1', 1, 2, (SELECT D FROM HOGE WHERE A = 1 - 1)+1+2)
の場合、D値がNULLになってしまいます。

oracle9では動作確認していますが、他のDBでも同様のことが出来ると思います。
なし
会議室デビュー日: 2004/09/17
投稿数: 17
投稿日時: 2004-10-25 14:16
引用:


コード:
INSERT INTO HOGE VALUES('AA', 1, 1, 2, NVL((SELECT D FROM HOGE WHERE A = 1 - 1), 0)+1+2);
INSERT INTO HOGE VALUES('BB', 2, 3, 4, NVL((SELECT D FROM HOGE WHERE A = 2 - 1), 0)+3+4);
INSERT INTO HOGE VALUES('CC', 3, 5, 6, NVL((SELECT D FROM HOGE WHERE A = 3 - 1), 0)+5+6);

---結果---
Q           A          B          C          D
-- ---------- ---------- ---------- ----------
AA          1          1          2          3
BB          2          3          4         10
CC          3          5          6         21





tak3さんがおしゃられる上記の方法を最初は取っていました。
クエリの部分は、CREATE VIEWでわざわざ作成していたのですが、
直接クエリを記入することができたんですね。

以前、直接クエリを与えるとエラーが出たのでできないものかと思っていました。


そして上記の方法から作成したクエリで、計算した値は常に0しか返ってこなくて
2レコード以降の計算が全ておかしくなっていました。
(こわれていたのではないと思います・・・)


tak3さんの方法で、A=1の時の計算がおかしくなる点ですが、
各フィールドの既定値を0に設定することで回避できたので
NULLを許して既定値=0のままにしています^^;


報告し忘れていましたが、
使用環境は、Microsoft SQL-Server 2000で、
VB6.0から、ADOを使用してアクセスしています。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)