• ベストアンサー
  • すぐに回答を!

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' これでもエラーになってしまい、うまくいきません。

共感・応援の気持ちを伝えよう!

  • 回答数2
  • 閲覧数4394
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.2
  • 23468
  • ベストアンサー率66% (6/9)

掲載されてるサイトの解説をちゃんと読めば、できると思いますけど… UPDATE sample SET flag=2 where date = ( SELECT max_date FROM ( SELECT MAX( date ) AS max_date FROM sample WHERE name='suzuki' ) AS temp1 );

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答ありがとうございます。 うまく動きました。 例示したサイトを参考に自分でも作ってみましたが、うまくSQL文を作れていませんでした。 うまく動かず先に進めなかったので、とても助かりました。

関連するQ&A

  • MySQLでサブクエリーが使えないため困っています

    MySQL3.23.58にて以下のSQLを実行したいのですが、 サブクエリーが利用できないため困っています。 やりたいことは、 1.memberテーブルにemailが重複したデータがあるため、 ユニークなemailを取得したい。 2.取得したemailを元にmemberテーブルを参照し、 シーケンシャルでユニークなidを取得したい。 3.その取得したidを元にflagが立っているものを取得したい。 以上になります。 実際に行いたいSQL文は以下になります。 select count(*) from member where id in ( select max(id) from member where email in ( select distinct email from M_MEMBER where email != '' and email not like '%@docomo.ne.jp' and email not like '%ezweb.ne.jp' and email not like '%ido.ne.jp' and email not like '%vodafone.ne.jp' and email not like '%@jp-%' ) ) and flag = 1; どうかよろしくお願いいたします。

  • サブクエリ

    サブクエリで、t2テーブルに列が無いか、t2テーブルの中でuflgの値が1である列がヒットする場合に真を返すなら、 where ... and 0=(select count(*) from t2) or 0<(select count(*) from t2 where uflg=1) のようにサブクエリに2つのselectを書かないと無理ですか?

  • MySQLのサブクエリ

    おせわになっております。 MySQLを愛用していますが、気になる疑問にぶつかりましたので、質問させてください。 ★MySQLの4.1系のサブクエリは、性能が悪いのですか? たとえば select * from t1 where key in ( select key from t2 where key2 in ( select key2 from t3 where col = 1)) のようなことをしようとしたとき、ものすごく遅いことがあります。 あきらめて、クエリを分けて、小分けに実行すれば、速いです。 サブクエリなどを高速に実行させる方法などありますでしょうか?MySQL5では違うものなのでしょうか? よろしくお願いします

その他の回答 (1)

  • 回答No.1
  • yambejp
  • ベストアンサー率51% (3827/7415)

>1.社員(列名:nameのsuzuki)の最新出勤日(列名:date)のflagを1にする >2.社員(列名:nameのsuzuki)の最新出勤日以外(列名:date)のflagを2にする updateの中に同じテーブルを含んじゃいけないんだから分けるしかないでしょう SELECT @max:=max(date) FROM sample; UPDATE sample SET flag=(date=@max,1,2);

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ご回答ありがとうございます。 UPDATEの中に同じテーブルを含むとダメだと私も思っていましたが、ネットで調べて例示したサイトに辿り着きました。 「23468」さんが回答して下さいましたが、 UPDATE sample SET flag=2 where date = ( SELECT max_date FROM ( SELECT MAX( date ) AS max_date FROM sample WHERE name='suzuki' ) AS temp1 ); というSQL文でうまく動きました。 SQL文は奥が深いですね。 今後とも、ご回答宜しくお願いします。

関連するQ&A

  • Update文について

    UPDATEについて SELECT * FROM A_table A JOIN B_table B ON (A.code = B.code) 上のように2つのテーブルをJOINして、 AのフィールドB.dateフィールドに A.dateフィールドを代入したいのですが、 どのようなUPDATE文を書けばよろしいでしょうか?

  • updateのWHERE句にサブクエリーを書く事は不可?

    同じテーブルに対し、サブクエリーを使用して 更新することは可能でしょうか? test 1 である条件にマッチしたIDに対し、 フラグを書き換えたいのですが・・動作しませんでした。 update test1 set flg = 0 WHERE test_id = ALL (SELECT test_id FROM test1 WHERE flg = 1 AND a = 0) #1093 - You can't specify target table 'test1' for update in FROM clause

    • ベストアンサー
    • MySQL
  • SQL内でループさせるような検索文

    以下の(1)のようなデータがあった場合、一つのSQL文で(3)の表が 取得できる方法はございますでしょうか? (1)table T_SAMPLE | UID | FLAG | CREATE_DATE | ------------------------------------------------ | 000 | A | 2009-01-26 00:00:00 |★ | 000 | A | 2009-01-26 00:00:10 | | 000 | B | 2009-01-26 00:00:20 | | 002 | A | 2009-01-26 00:00:05 |★ | 002 | B | 2009-01-26 00:00:13 | | 002 | A | 2009-01-26 00:01:00 | | 002 | B | 2009-01-26 00:02:02 | | 003 | B | 2009-01-26 00:05:00 |★ | 004 | B | 2009-01-26 00:00:00 |★ | 004 | B | 2009-01-26 00:00:15 | | 004 | A | 2009-01-26 01:00:00 | | 005 | B | 2009-01-26 00:00:11 |★ | 005 | B | 2009-01-26 00:04:05 | (2)同じUIDがあった場合、CREATE_DATEが早い情報(上表★)を使用 | UID | FLAG | CREATE_DATE | --------------------------------------------------- | 000 | A | 2009-01-26 00:00:00 |★ | 002 | A | 2009-01-26 00:00:05 |★ | 003 | B | 2009-01-26 00:05:00 |★ | 004 | B | 2009-01-26 00:00:00 |★ | 005 | B | 2009-01-26 00:00:11 |★ (3)FLAGでカウント <= 取得したい結果 | COUNT(FLAG) | FLAG | -------------------------------- | 2 | A | | 3 | B | イメージとしては、 [処理a] select FLAG from T_SAMPLE where UID = '000' order by CREATE_DATE limit 0,1 ×それぞれUID とすると、上記(1)→(2)で select UID,[処理aの結果においてUIDに対応したFLAG] from T_SAMPLE group by UID という状態の結果が一度のSQLで取得できればよいと考えているのですが。 実際にこの処理を実施する際は、自由に指定されるCREATE_DATEの範囲で絞り込むため、別テーブルを作って、、、等の処理は避けたいのです。 最適な方法がございましたら、なにとぞご教示願います。

    • ベストアンサー
    • MySQL
  • MySQLのサブクエリーでエラーがでます

    現在MySQLを使って開発をしています。 SQLもMySQLもまだあまり使ったことがないのでなにか大きな勘違いをしている かもしれませんが、自分で作ったデータベースにMysqlコマンドでアクセスし、 以下のようにselectを行うとsyntaxエラーが発生します。 mysql> select CREATE_DATE from user where cust_id = (select cust_id from customer where memo = 'memo'); ERROR 1064: You have an error in your SQL syntax near 'select cust_id from customer where memo = 'memo')' at line 1 しかしサブクエリーの内容も、その前のselectもそれぞれ下記のように単体で実行すると正常に動作するので、文法的には間違っていないと思います。 ERROR 1064のsyntaxエラーは何を指しているのでしょうか? ぜひご教示ください。 mysql> select cust_id from customer where memo = 'memo'; +---------+ | cust_id | +---------+ | 1 | +---------+ 1 row in set (0.00 sec) mysql> select CREATE_DATE from user where cust_id = '1'; +-------------+ | CREATE_DATE | +-------------+ | 2001-07-23 | +-------------+ 1 row in set (0.00 sec)

  • MySQL サブクエリについて

    MySQL 5.1.32-community tb1 --------------------- |no| thread | date | -------------------- |1 |スレッドA| 2011/1/25 | -------------------- |2 |スレッドB| 2011/1/28 | |-------------------- tb2 --------------------- |no| mes | date | -------------------- |1 |コメントA| 2011/1/25 | -------------------- |1 |コメントB| 2011/1/28 | |-------------------- |1 |コメントC| 2011/1/29 | |-------------------- |2 |コメントD| 2011/1/25 | |-------------------- |2 |コメントE| 2011/1/28 | |-------------------- 下記が取り出したいデータです。 スレッドNo、スレッド名、スレッドの最新コメント、日付、コメント数です。 ---------------------------------------- |no|thread | mes | date |count(*) | ---------------------------------------- |1 |スレッドA | コメントC | 2011/1/29 |3 | ---------------------------------------- |2 |スレッドB | コメントE | 2011/1/28 |2 | |---------------------------------------- select * from tb1 as A left join tb2 as B on A.no = B.no where not exists( select * from tb2 C where B.no = C.no and B.date < C.date ) ; 取りあえず上記のSQL文でスレッドごとのコメント数(count(*))以外のデータを取り出せるようにはなりました。 スレッドごとのコメント数を追加して取り出そうと思っています。 スレッドごとのコメント数(count(*))まで取り出せるSQL文の作り方が解る方がいましたら、是非ご教授お願い致します。

    • ベストアンサー
    • MySQL
  • 複雑な条件下におけるupdate文について

    sqlserver(2008R2)についてクエリ文が上手く書けません。 お手数をおかけいたしますが、お分かりになる方はご教授いただければと 思います。 まず、元となるテーブルおよび作成したい完成系は添付ファイルをご確認下さい。 personal_id、personal_name、personal_address、personal_tel、personal_date列を 持つテーブル(personal_table)から 「select * into #table01 personal_table」に よって一時テーブル#table01を作成し、personal_name・address・telがnullの場合に、 personal_dateが直前時におけるnull以外の値をセットしたいと思っています。 (ただし、セットするのはpersonal_id毎で、最もpersonal_dateが若い者には 必ずpersonal_name・address・telが入っているものとします)。 なお、以下は私が作成したクエリになります。 項目1つずつっと思い、 とりあえずpersonal_nameをpersona_idおよびpersonal_dateを用いて updateしようと思ったのですが、personal_nameがすべてnullになってしまいました。 --------------------------- select * into #table01 from personal_table update #table01 set personal_name = (select personal_name from #table01 A where #table01.personal_id = A.personal_id AND #table01.personal_date = (select MAX(A.personal_date) from #table01 A where #table01.personal_date > A.personal_date AND #table01.personal_id = A.personal_id)) SELECT * from #table01 --------------------------- 完成系を作成するにあたってどのようなクエリを書けばよろしいのか、 ご教授いただければと思います。

  • サブクエリーのパフォーマンスについて

    こんばんわ。 ある書籍にサブクエリーを【1】より【2】にした方がパフォーマンスがいいと書いてありました。 パフォーマンスがいい理由を教えて頂けないでしょうか?? 【1】 UPDATE Absenteeism SET severity_points= 0, reason_code = 'long term illness' WHERE EXISTS (SELECT * FROM Absenteeism AS A2 WHERE Absenteeism.emp_id = A2.emp_id AND Absenteeism.absent_date = (A2.absent_date + INTERVAL '1' DAY)); 【2】 UPDATE Absenteeism AS A1 SET severity_points = 0, reason_code = 'long term illness' WHERE EXISTS (SELECT * FROM Absenteeism AS A2 WHERE A1.emp_id = A2.emp_id AND (A2.absent_date + INTERVAL '1' DAY) = A1.absent_date); よろしくお願いします。 以上

  • 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) 変な質問ですいませんが、何か方法があるのでしょうか。 よろしくお願いします。

  • サブクエリを利用したSQL文から複数の抽出条件

    例えば、以下のようなサブクエリを利用したSQL文があります。 SELECT table_a.* FROM table_a LEFT JOIN (SELECT table_b.* FROM table_b LEFT JOIN table_c ON (table_b.id = table_c.bid) WHERE table_b.type='1') AS tbl ON (table_a.id = tbl.aid) このSQL文にWHERE句で条件を指定したいのですが、サブクエリで指定しているtblテーブルのvalueフィールドが「1」と「20」のものを抽出したいと思います。 WHERE (tbl.value='1' AND tbl.value='20') としても結果が帰って来ません。 これは、WHEREする条件の数だけ、サブクエリでテーブルを作って条件を指定するのでしょうか? 効率が悪そうなので、他の方法があるのではと思いご質問させて頂きました。 お分かりになる方がいれば、よろしくお願いします。

  • サブクエリーについて教えてください。

    こんにちは!以下のようなことがサブクエリーを使用してできるか?他にどんな方法があるか、アドバイスをお願いします。 あるテーブル(TABLE)から2段階でデータをselectし、計算させたいのですが分かりません。 一段階目 select a,b,c,d,e,f from TABLE where a='A' and b='B' 二段階目(上記の結果を使って、ここからが分かりません) select c,d,e,sum(f) as 結果 from TABLE(?) group by c,d,e having e='E' やりたいことの概要: 1. a='A' and b='B'でデータを抽出 2. 1.で抽出したデータに対してグループ化して集計する これを一回で実行するにはどのようにしたら良いでしょうか?サブクエリーでできそうだと思い、いろいろ調べましたが、よく分かりませんでした。 よろしくお願いします。