• 締切済み

Sql文のUpdateと副問い合わせで困っています。

お世話になっております。Sql初心者でUpdate文の書き方で困っております。ご教授の程宜しくお願い致します。 下記のような2つのテーブルがあります。 関係はTotalが合計を表すテーブルでDetailが明細を表すテーブルです。OTとNoの組み合わせで一意となります。TotalテーブルのTotalAmountはDetailテーブルのAmountの合計です。 行いたいUpdateは『TotalAmountとTotalの合計が合わないもののみTotalAmountをOTとNoで紐ずくDetailテーブルのAmountの合計で更新する』です。 ■テーブル名:Total ------------------------------------------------------- 列名) OT No TotalAmount ------------------------------------------------------- 20 100000 0 20 100001 0 20 100002 10 ■テーブル名:Detail ------------------------------------------------------- 列名) OT No Amount ------------------------------------------------------- 20 100000 10 20 100000 10 20 100001 20 20 100001 30 20 100002 5 20 100002 5 ■作成したSql update Total set TotalAmount = (select Sum(Amount) from Detail Inner Join Total on Detail.OT = Total.OT and Detail.No = Total.No group by Total.TotalAmount,Total.OT,Detail.OT,Total.No,Detail.No having Total.TotalAmount <> sum(Detail.Amount) ) where OT = (select OT from Detail) and No = (select No from Detail) and TotalAmount <> (select sum(Amount) from Detail) いろいろ試行錯誤しながら作成しましたが『サブクエリは複数の値を返しました ~ 』というエラーが出てしまいます。 つっこみどころ満載だと思いますがご教授の程宜しくお願い致します。

みんなの回答

  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.3

>この部分は何を行っているのでしょうか? >>isnull(d.TotalAmount,0) そもそもleft outer joinにしている理由は「Totalにはあるけど、(削除されたなどで)Detailにはないというケース」を想定してのものです。 Detailが万一なくなっていれば、やはりTotalAmountは0にしたいでしょうから。 上記のケースではDetail側はデータがないので、NULLになります。 ISNULLは「NULLならばゼロにする」という関数です。 これにより上記ケースでもTotalAmountを0にできます。

全文を見る
すると、全ての回答が全文表示されます。
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.2

分かりやすく考えるには、一旦Detailを集計してからJOINした方がよいですね。 update Total set TotalAmount=isnull(d.TotalAmount,0) from Total t left outer join (select OT,No,sum(Amount) TotalAmount from Detail group by OT,No) d ON d.OT=t.OT and d.No=t.No where t.TotalAmount<>isnull(d.TotalAmount,0)

ctyhf098
質問者

補足

なるほどです。ありがとうございます。 更新もきれいにできました。 1つ質問です。 この部分は何を行っているのでしょうか? >isnull(d.TotalAmount,0) 宜しくお願いします。

全文を見る
すると、全ての回答が全文表示されます。
  • t_ohta
  • ベストアンサー率38% (5096/13320)
回答No.1

そもそも1回のクエリーでTotalテーブル全行のTotalAmountを更新する事自体が無理な気がします。 set TotalAmount = (...) の部分のサブクエリーは where句が無いため group byしか結果の組み合わせ分(複数)の値が返ってくるので、どの値にアップデートしたらいいのか特定できなくてエラーになります。 ※ サブクエリーだけ一回実行してみるとわかると思います。 まず、TotalテーブルからOTとNoとTotalAmountの各値を取得しておき update Total set TotalAmount = (select Sum(Amount) from Detail where OT = [OTの値] and No = [Noの値]) where Detail where OT = [OTの値] and No = [OTの値] and TotalAmount <> (select Sum(Amount) from Detail where OT = [OTの値] and No = [Noの値]); をぐるぐる回すのがいいのではないでしょうか。

ctyhf098
質問者

お礼

ご指摘ありがとうございます。 特に↓部分なるほどです。 >set TotalAmount = (...) の部分のサブクエリーは where句が無いため group byしか結果の組み合わせ分(複数)の値が返ってくるので、どの値にアップデートしたらいいのか特定できなくてエラーになります。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • SQL文で作ったデータを使ったUPDATE

    環境はMySQL5.6です。 下記のテーブルccがあります。 【cc】 shisan  user 500  tanaka 1000  mikami 400   tanaka 1300  mikami SELECT Total, user FROM (SELECT SUM( cc.shisan ) AS Total, user FROM cc GROUP BY user) AS t1 とすることによりSQL上にt1テーブルを作ることが出来ます。 【t1】 Total  user 900  tanaka 2300  mikami 次に、このt1テーブルのTotalの数値を下記のmoney_tableにあるcash欄に挿入(UPDATE)したいと考えています。 【money_table】 cash  user 0   tanaka 0   mikami そこで下記のSQL文を作ったのですがエラーになります。 UPDATE money_table,cc SET money_table.cash=t1.Total FROM (SELECT Total, user FROM (SELECT SUM( cc.shisan ) AS Total, user FROM cc GROUP BY user) AS t1) WHERE money_table.user=t1.user どこがいけないのかご指導いただけませんでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • select文のサマリー

     select sum(A.列名1)  --列名1の型はnumber  from テーブル名 A where A.列名2 = 定数  and A.列名3 <> 定数; と言った簡単なSQLなのですが、 結果としてnull値が返ることはあるでしょうか? count では必ず数値が返ると思うのですが・・・sumの場合もヒットする値が1件もなかった場合0が返るのでしょうか?  また、sum()またはcnt()でnullが返されるような条件があるとしたらどんな時でしょうか?

  • SQL 副問い合わせ

    以下のaテーブルのcardidと、bテーブルのnoが同じで、 かつ、bテーブルのryodtmが前月のデータを抽出する以下のsqlを、 aテーブルのcardidが、bテーブルのnoと同じで、かつ、ryodtmが前月分、 または、cテーブルのchangcardと同じで、かつ、ryodtmが前月分のを抽出する場合、 どうすればいいでしょうか? select * from a where cardid in ( select distinct(no) from b where kdncresbt ='1' and ryodtm >= TO_CHAR(ADD_MONTHS(TRNC(SYSDATE,'MONTH'), -1),'YYYYMM' ) || '01' and ryodtm < TO_CHAR(SYSDATE,'YYYYMM') || '01' )

  • MySQLのUPDATE文でサブクエリ

    MySQLのUPDATE文でサブクエリの使い方について教えて下さい。 MySQLのUPDATE文でサブクエリを使うと「#1093 - You can't specify target table 'exam' for update in FROM clause 」というエラーになってしまいます。 「あるテーブルに対してデータを追加・更新する場合、同じテーブルをサブクエリーに使えない」 「サブクエリー内のFrom句はテンポラリテーブルとして扱うことが可能」 ということはわかりましたが、これに従いSQL文を変更してもうまくいきません。 どのようにSQL文を作ったら良いか教えていただければと思います。 環境 PHP:5.1.6 MySQL:5.0.77 ------具体的なSQL文--------------------------------------- テーブル名:sample カラム名:date(DATETIME型),name,flag 上記テーブルに対して、 1.社員(列名:nameのsuzuki)の最新出勤日(列名:date)のflagを1にする 2.社員(列名:nameのsuzuki)の最新出勤日以外(列名:date)のflagを2にする という処理をしたいと思います。 まず、SELECT文を作ってみました。 1.最新出勤日データを抽出 SELECT * FROM sample WHERE (date= (select max(date) from sample)) and name='sizili' 2.最新出勤日以外のデータを抽出 SELECT * FROM sample WHERE not (date= (SELECT max(date) FROM sample)) and name='suzuki' これをUPDATE文に変更すると、 #1093 - You can't specify target table 'exam' for update in FROM clause というエラーになります。 上記をUPDATE文に変更 1.最新出勤日データを抽出 UPDATE sample SET flag=1 WHERE (date= (select max(date) from sample)) and name='sizili' 2.最新出勤日以外のデータを抽出 UPDATE sample SET flag=2 WHERE not (date= (SELECT max(date) FROM sample)) and name='suzuki' エラー文を検索したところ下記のような情報を見つけることができました。 「仕事SPOT」 MySQLでサブクエリ(エラー#1093を回避する方法) http://wsjp.blogspot.com/2009/12/mysql1093.html 「あるテーブルに対してデータを追加・更新する場合、同じテーブルをサブクエリーに使えない」 「サブクエリー内のFrom句はテンポラリテーブルとして扱うことが可能」 と記載されています。 このページに掲載してあるように変更を加えてみました。 1.最新出勤日データを抽出 UPDATE sample SET flag=1 WHERE (date= (select max(date) as test_max from sample)) as text_tb and name='sizili' 2.最新出勤日以外のデータを抽出 UPDATE sample SET flag=2 WHERE not (date= (SELECT max(date) as test_max FROM sample)) as test_tb and name='suzuki' これでもエラーになってしまい、うまくいきません。

    • ベストアンサー
    • PHP
  • SQLの合計関数について

    お世話になります。 「価格(price)」と「個数(amount)」を掛けあわせてものの合計を取得したいのですがどのようにしたらよろしいでしょうか? | price | amount | ID ――――――――――― |  101 |  200 |0001 |  102 |  300 |0001 |  103 |  400 |0001 |  101 |  100 |0001 |  102 |  200 |0001 |  103 |  300 |0001 SELECT sum(price) as total FROM LIST Where id= '0001'; 上記の場合ですとpriceの合計だけなのですがこれを各行ごとに「price * amount」をしたものの合計を求める方法をご教授頂けたら幸いです。 よろしくお願いいたします。

  • SQL文について困っています

    ID(NUMBER型)と NUM(NUMBER型)と nenngetu (date型)を持ったテーブルAAAから、 ID=1000 のなかで日時が一番古い処理NOをselectするSQL文を書きましたが上手く実行されません。 select NUM from AAA where nenngetu = (select min(nenngetu) from AAA) and ID=1000; ID=1000の条件をはぶき、 select NUM from AAA where nenngetu = (select min(nenngetu) from AAA); でしたら、実行できました。 oracleで実行しようとしています。 どなたか、書き方を教えてください。

  • UPDATE文について

    昨日こちらで自分の間違ったSQL文をご指摘頂き 時間計算の処理は実装する事が出来たのですが その後の計算処理が終わった後、計算結果をDBに格納する処理で 再度躓いてしまったので、再度のご教授お願いします。 $sql = "SELECT SUM(ROUND(労働時間/100, 0)) + ROUND(SUM(MOD(労働時間,100)) / 60, 2) AS total     FROM 労働時間テーブル WHERE id = 'ログインしている人のID';"; $total_Time = pg_query($con, $sql); $total_Time = pg_fetch_result($total_Time, 0, 'total'); // 確認のため、表示 echo $total_Time; で値はきちんと表示されおります。 しかし、この後UPDATE文で $sql = "UPDATE 労働時間テーブル SET 総労働時間 = '$total_Time' WHERE id = 'ログインしている人のID';"; pg_query($con, $sql); と打ち試しましたが、echoの時に表示された値がDBに格納されません。(>_<) 試しに $sql = "UPDATE 労働時間テーブル SET 総労働時間 = '$total_Time' WHERE id = 'ログインしている人のID';"; の'$total_Time'をSELECT文に変更したりもしましたが、echoの時に 表示されていた値とは違う値がDBに格納されるようになってしまいました。 どのように解決したらよいか、悩んでおります。 そもそもの考え方から間違っているのでしょうか? ご教授の程、よろしくお願い致します。

  • SQL文でのデータの取得が上手くいきません

    初めて質問させていただきます。 こちらのカテゴリで良いのか分からなかったのですが、よろしくお願いいたします。 SQL文を作成しているのですが、上手くいかず困っている状況です。 要件としてはテーブルAにユーザーの情報が格納されているのですが、 キーの一つとして世代(SEDAI_NO)(日付)を持っております。 今回取り出したいデータは該当ユーザーの処理日以前の最新のデータを 取得したいと思い以下のSQL文を作成しましたが、上手く行かず、最新世代を含むそれ以前の世代のデータを取得してきています。 どこがおかしいのでしょうか? よろしくお願いいたします。 【作成したSQL】 select * from テーブルA テーブルA’ where (USER_ID=該当のユーザーID) and (SEDAI_NO = (select max(SEDAI_NO) from テーブルA where SEDAI_NO = テーブルA’.SEDAI_NO AND 処理日 >= テーブルA'.SEDAI_NO)

  • updateしてもSQLを終了すると元に戻る

    Oracle_9→access2002 で外注開発されたシステムを利用しています さて、Oracle、SQL_Plusの[update TABLE1 SET FIELD1 = 'X' WHERE FIELD1 IS NULL]等でデータ更新後、[select 列名リスト FROM TABLE1 WHERE 検索条件]で確認すると確かに更新されているが、SQLを終了後、再起動すると元に戻ってしまいますが、どんな原因が考えられますか?update実行後に確定操作等あるのですか? Oracleはまったく初心者ですがお願いします

  • SQL文について質問があります。

    PostgreSQLのSQL文で質問があります。 kekktaテーブルの構成 ---------------------- name:varchar(64) score : int 4 day : date ---------------------- 現在kekkaテーブルには以下のレコードが格納されています。 ------------------------------- yamada| -2|2003-04-30 yamada|-16|2003-05-01 yamada| 3|2003-05-02 yamada|-23|2003-05-02 honda |-12|2003-05-10 yamada| 12|2003-05-15 yamada| -6|2003-05-20 yamada| -8|2003-06-01 ------------------------------- このレコードで 2003年5月のyamadaさんのレコードの最新日付からの scoreの合計を取得したいと考えています。 ---------------------------------- select name, sum(score) from kekka where name='yamada' and day like '2003-05%' group by name offset 0 limit 4; (このSQLはもちろんうまくいきません) ---------------------------------- <出力したい結果> name | sum(score) --------------------- yamada | -14 です。 SQLがうまくできません。 宜しくお願いいたします。