• 締切済み

UPDATE文を教えてください

管理テーブルというテーブルがあります。 フィールド構成は、会社コード(6)/支店コード(2) SEQNO(2)/管理年月(6)/管理番号(8)となっていて、SeqNOがKeyとなっています。   会社コード|支店コード SeqNO 管理年月 管理番号 (1) 000001| 01 | 01 | 200503 |00000000 (2) 000001| 01 | 02 | 200503 |00000000 (3) 000001|  02 |  03 | 200503 |00000000 (4) 000001|  02 |  04 | 200503 |00000000 (5) 000001| 01 | 05 | 200502 |11111111 (6) 000001| 01 | 06 | 200502 |11111111 (7) 000001| 02 | 07 | 200502 |22222222 (8) 000001| 02 | 08 | 200502 |22222222 こんな感じでデータがあります。 会社コード/支店コード/管理年月が同じものの管理番号は、必ず同じデータが入ります。 これは、実際のデータはさらに複雑ですが、簡単にするため変なデータに思えると思います。まあそこは気にしないでください。 実は、(1)~(4)の管理番号がミスでデータが落ちてしまいました。 管理テーブルの管理年月が200502の会社コードと支店コードが同じ管理番号を同じデータの200503の管理番号に更新するSQLを教えてください。 一応作ってみましたが、 ”単一行副問合せにより2つ以上の行が返されます。”が出てしまって・・ 分からないので教えてください。 UPDATE 管理テーブル T1 SET T1.管理番号 = (SELECT T2.管理番号 FROM 管理テーブル T2 WHERE T2.会社コード = T1.会社コード AND T2.支店コード = T1.支店コード AND T2.管理年月 = 200502) WHERE (T1.会社コード,T1.支店コード) IN (SELECT T3.会社コード,T3.支店コード FROM 管理テーブル T3 WHERE T3.管理年月 = 200503 GROUP BY T3.会社コード,T3.支店コード)

  • Oracle
  • 回答数6
  • ありがとう数8

みんなの回答

  • iiikkk
  • ベストアンサー率37% (92/247)
回答No.6

UPDATE 管理テーブル T1 SET T1.管理番号 = nvl(( SELECT DISTINCT T2.管理番号 FROM 管理テーブル T2 WHERE T2.会社コード = T1.会社コード AND T2.支店コード = T1.支店コード AND T2.管理年月 = 200502 ), 00000000) WHERE T1.管理年月 = 200503 これではどうでしょうか?

NYAN99
質問者

お礼

ありがとうございます。これも出来ますね。 本当にいろいろやり方があるんだなと。 すごく勉強になりました。

回答No.5

#3ですが.. よくよく見ると・・、更新対象レコードの限定の仕方がうまくない。 UPDATE 管理テーブル T1 SET T1.管理番号 = (SELECT T2.管理番号 FROM 管理テーブル T2 WHERE T2.会社コード = T1.会社コード AND T2.支店コード = T1.支店コード AND T2.管理年月 = 200502 and ROWNUM=1 ) WHERE (T1.会社コード,T1.支店コード) IN (SELECT T3.会社コード,T3.支店コード FROM 管理テーブル T3 WHERE T3.管理年月 = 200503 GROUP BY T3.会社コード,T3.支店コード) and T1.管理年月 = 200503 /* <========ここ== */ ただ、更新件数も多くなるはずだし、管理年月=200502のレコードの管理番号が"00000000"になることは無いと思います。 管理年月=200503以外のレコードまで、管理年月=200502の管理番号で更新されるハズです。 なので、事態が理解できないカンジです。

NYAN99
質問者

お礼

ありがとうございました。 このSQLでうまく行きました。結構こういう変なファイル が多いので今後活用させて頂きます。 とても勉強になりました。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

#1です。 UPDATE 管理テーブル T1 SET T1.管理番号 = (SELECT MAX(T2.管理番号) FROM 管理テーブル T2 WHERE T2.会社コード = T1.会社コード AND T2.支店コード = T1.支店コード AND T2.管理年月 = 200502 GROUP BY T2.会社コード, T2.支店コード) WHERE T1.管理年月 = 200503 すみません。管理番号を抽出する方のselectに集計関数付け忘れました。

NYAN99
質問者

お礼

ありがとうございました。エラーもなく更新件数がぴったり合ったので出来た!と喜びましたが、 結果を見ると管理番号が全て0000000に置き換わってしまいました。これはやばい!です。

回答No.3

レコード(1)~(4)を更新するとき、相関性のあるデータの検索条件が甘いので、 レコード(1)に対し、(5)(6)が該当する。 レコード(2)に対し、(5)(6)が該当する。 レコード(3)に対し、(7)(8)が該当する。 レコード(4)に対し、(7)(8)が該当する。 という感じで、複数該当するので、オラクルはどちらを採用して良いか不明なため エラーとしています。 今回のケースではどちらでも良いということなので、どちらでも良いから1件だけ限定する 条件を書き加えればOKです。 UPDATE 管理テーブル T1 SET T1.管理番号 = (SELECT T2.管理番号 FROM 管理テーブル T2 WHERE T2.会社コード = T1.会社コード AND T2.支店コード = T1.支店コード AND T2.管理年月 = 200502 and ROWNUM=1 /* <===========1件だけよ==== */ ) WHERE (T1.会社コード,T1.支店コード) IN (SELECT T3.会社コード,T3.支店コード FROM 管理テーブル T3 WHERE T3.管理年月 = 200503 GROUP BY T3.会社コード,T3.支店コード)

NYAN99
質問者

お礼

ありがとうございました。エラーもなく更新件数がぴったり合ったので出来た!と喜びましたが、 結果を見ると管理番号が全て0000000に置き換わってしまいました。これはやばい!です。

  • raphel_7
  • ベストアンサー率34% (86/252)
回答No.2

間違ってるかもしれませんが・・・。 UPDATE 管理テーブル T1  SET T1.管理番号 = (SELECT T2.管理番号              FROM (SELECT T3.会社コード,T3.支店コード                  FROM 管理テーブル T3                  WHERE T3.管理年月 = 200503                  GROUP BY T3.会社コード,T3.支店コード                 ) T2              WHERE T2.会社コード = T1.会社コード               AND T2.支店コード = T1.支店コード               AND T2.管理年月 = 200502             ) こんな感じでどうでしょう。

NYAN99
質問者

お礼

ありがとうございました。参考にさせて頂きました。 でも T2.管理年月 = 200502でエラーが出てしまいました。思うに管理年月が選択されていないからでは・・

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

これでどうかな? UPDATE 管理テーブル T1 SET T1.管理番号 = (SELECT T2.管理番号 FROM 管理テーブル T2 WHERE T2.会社コード = T1.会社コード AND T2.支店コード = T1.支店コード AND T2.管理年月 = 200502 GROUP BY T2.会社コード, T2.支店コード) WHERE T1.管理年月 = 200503 更新対象のレコードの抽出条件は「T1.管理年月 = 200503」だけで十分かと。 あとは、更新する値を抽出する方で、GROUP BYを使って単一行を返します。

関連するQ&A

  • 【初歩的な質問ですが・・・】 SQL文書き方がわかりません

    SQLの知識に乏しい者です。 よろしくお願い致します。 ●テーブルA ・会計コード ・年度 ・部署番号 ・社員番号 ・その他幾つかのデータ ※Where句で「年度>2002年」以降を抽出 のテーブルがあります。 この時、Bテーブルで ●テーブルB ・会計コード(主キー) ・年度 ・部署番号(主キー) ・社員番号(主キー) ・その他幾つかのデータ ※Aテーブルで抽出されたデータの中から絞り込む というテーブルを抽出するSQL文を組みたいのですが、効率の良いやり方がわかりません。 副問合せで  Select [B表で抽出した列名…]  From B表  Where 会計コード = (Select 会計コード               From A表               Where 年度 > '2002')  AND 部署番号 = (Select 部署番号             From A表               Where 年度 > '2002') ・・・・以下省略 の様に書くと効率が悪い気がしました。 (実際には、副問合せが6個書くことになるため) 良い書き方を知っている方がいらっしゃいましたら、よろしくお願い致します。

  • 意味を教えてください。

    以前SQLのアドバイスを頂いたのですが、 (つい締め切ってしまったので・・) その書き方で質問したいのです。Oracle8i update T1 set (合計1,合計2) = ( select T1.合計1 - T2.金額1, T1.合計2 - T2.金額1 - T1.金額2 from T2 where T1.年=T2.年 and T1.個人コード=T2.個人コード and T2.番号=01 and T2.合計1>0 ) where (T1.年,T1.個人コード) in ((2003,1000)) and exists ( select 1 from T2 ・・・(1) where T1.年=T2.年 and T1.個人コード=T2.個人コード and T2.番号=01 and T2.合計1>0 ) このSQLはどういう順番で動くのでしょうか? 特に(1)のSelect 1は、どういう意味なのでしょうか? 何が抽出されるのでしょうか?

  • UPDATE文(副問合せ?)について

    うまく説明できないのですが、下記のようなテーブルがあります。 テーブル名:A 項目: A1 A2 A3 A4 AテーブルのA1項目に「5」がセットされているデータについて、 A2に123、A3に321をセットしたいのです。 うまくいかない例ですが、下記のようなイメージです。 UPDATE A set A2=123,A3=321 FROM (SELECT * FROM A WHERE A1 = '5') ちなみに下の書き方はダメです。 「SELECT * FROM A WHERE A1 = 5」の部分は、必ず使用し、変更不可です。 × UPDATE A set A2=123,A3=321 WHERE A1 IN(SELECT A1 FROM A WHERE A1 = 5) 変な質問ですいませんが、何か方法があるのでしょうか。 よろしくお願いします。

  • VIEWのレスポンス改善について

    現在オラクル10gでレスポンス改善の勉強をしています。 下記のようなデータ、テーブルがあるとき有効なSQLの書き方が分かりません。 テーブル名;MASTER_CODE カラム名 ・区分コード ・コード ・レベル ・名称 サンプルデータ 区分コード、コード、レベル、名称 1000 10 1 東京本部 1000 11 1 大阪支店 1000 12 1 福岡支店 1000 10 2 営業部  1000 11 2 開発部 1000 12 2 総務部 1000 10 3 1課 1000 11 3 2課 1000 12 3 3課 1100 10 1 A商事 1100 11 1 B商事 1100 12 1 C商事 1100 10 2 A商事の住所 1100 11 2 B商事の住所 1100 12 2 C商事の住所 テーブル名;TRAN_TABLE カラム名 ・連番 ・支店コード ・部署コード ・課コード ・得意先コード ・得意先住所コード サンプルデータ 連番、支店コード、部署コード、課コード、得意先コード、得意先住所コード 1 10 12 10 10 10 2 11 11 12 11 11 3 12 10 11 12 12 上記のようなテーブルがあり トランザクショテーブルからマスタを参照し、 コードではなく名称で取得できるVIEWを作成しました。 select * from TRAN_TABLE A, (select コード、名称 from MASTER_CODE where 区分=1000 AND レベル=1) SHITEN, (select コード、名称 from MASTER_CODE where 区分=1000 AND レベル=2) BUSHO, (select コード、名称 from MASTER_CODE where 区分=1000 AND レベル=3) KA, (select コード、名称 from MASTER_CODE where 区分=1100 AND レベル=1) TORIHIKISAKI, (select コード、名称 from MASTER_CODE where 区分=1100 AND レベル=2) TORIJUSHO WHERE SHITEN.コード(+)=A.支店コード AND BUSHO.コード(+)=A.部署コード AND KA.コード(+)=A.課コード AND TORIHIKISAKI.コード(+)=A.得意先コード AND TORIJUSHO.コード(+)=A.得意先住所コード  上記のSQLだとレスポンスがよくありません。 (実際はマスターテーブルに多くのデータを登録してあります) 同じMASTER_CODEを使用しているので、もっと良い方法があるのでしょうか? ご回答宜しくお願いします。

  • 複数テーブルのUPDATE

    タイトルの通り、複数テーブルのUPDATEを行いたいと思っています。 私なりには、以下のようなコードでテーブルを作成しようとしましたが、作成できませんでした。 エラー内容としては、 update table_1, table_2 SET のtable_1, が間違ってます的なエラーでした。 update table_1, table_2 SET table_1.updatetime=getdate(), WHERE table_1.SeqNo = table_2.SeqNo AND table_1.SeqNo = @SeqNo 以上、緊急の内容であったため、十分調べていない点があるかもしれませんが、何卒、ご存知の方ご教授お願い致します。

  • 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文について

    テーブルの結合について教えてください。 (DBはオラクルです) select * from table1,table2 where table1.カラム名=table2.カラム名; で、結合が出来ることは分かりました。 やりたいことはテーブルの結合と、ある期間のデータを持ってきたいのです。 select カラム名 from table1 where カラム名 between '20020213' and '20020218'; で期間を決めて引き出すやり方も分かっています。 一度に結合と期間を決めて引き出すやりかたってどうすればよいですか? それとも不可能ですか? 教えてください。

  • sqlのwhereで指定した条件の前後を取得したい

    テーブル=T) KEY DATA 001 あ 002 い 003 う 004 え 005 お SQL) SELECT DATA FROM T WHERE KEY = 003 ; 上記のSQLでは、「う」のデータしか取得できませんが、 「003」の前後1件、合計3件の「い」「う」「え」を取得する方法を教えて下さい。 ちなみに、 SELECT DATA FROM T WHERE KEY >= 003 AND ROWNUM <= 2 と SELECT * FROM ( SELECT DATA FROM T WHERE KEY < 003 ORDER BY KEY DESC ) WHERE ROWNUM < 1 のUNIONでは上手く行きませんでした。 よろしくお願いします。

  • SQL文 この部分はなんていうのでしょう?

    SELECT T_テーブル1.フィールド1 FROM T_テーブル1 ORDER BY T_テーブル1.フィールド1; なら、 ”ORDER BY句” SELECT T_テーブル1.フィールド1 FROM T_テーブル1 WHERE (((T_テーブル1.フィールド1)="A")); なら ”WHERE句” と言いますが、 DELETE Table1.* FROM Table1; や UPDATE テーブル1 Set テーブル1.フィールド1 = "い" WHERE (((テーブル1.フィールド1)=”あ")); や DROP Table Table1; の deleteやupdateやdropの部分は何て言うのでしょうか? そのまま、SELECT句DELETE句などというのでしょうか?

  • select文の書き方で分からないところがあります

    どうしても分からないので教えてください。 先人の書いたphpの記述を解析しています。 postgreSQLとやり取りしている部分に、次のようなselect文の記述があります。 select lpad(seq_no,shiyo_keta,'0'),seq_min,seq_max from seqno_info where seq_key='YAMATODENPYO'; 実行すると次のようなエラーがでます。 ERROR: 関数lpad(bigint, smallint, unknown)は存在しません 茵 1: select lpad(seq_no,shiyo_keta,'0'),seq_min,seq_max from seqn... (lpadのあたりに印が付いていましたが、ここではずれるので消してあります。) HINT: 指定名称、指定引数型に合う関数がありません。明示的な型キャストが必要かも しれません テーブルの型は次のようになっています。 \d seqno_info Table "public.seqno_info" Column | Type | Modifiers ------------+----------+----------- seq_key | text | not null seq_no | bigint | seq_min | bigint | seq_max | bigint | shiyo_keta | smallint | 以下がそれぞれに入っているデータです。 select seq_no from seqno_info; seq_no -------- 999 (1 row) select shiyo_keta from seqno_info; shiyo_keta ------------ 3 (1 row) 調べても有力な情報が見当たらず困っています。 どなたか、ご教示ください。