質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

2431閲覧

AccessVBA・SQLでUPDATEステートメントでのサブクエリ代用方法

tatsutatsu

総合スコア9

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/10/02 10:17

前提・実現したいこと

AccessVBA、SQLを使用しています。
条件にあったレコードの対象フィールドにフラグ("選択済")を入力して、条件を変えてまたフラグを入力して、という連続した処理を行いたいのですが、AccessVBAでSQLを書くと、UPDATEステートメントではサブクエリを使えないらしい、ということが調べてみて分かりました。

下記のようなコードをイメージしていました。
また、後続のコードではこのコードのサブクエリWHERE句の条件を変えたり、フラグ入力するフィールドを変えたりしたものをいくつも書いて、連続した処理としたいです。

UPDATEで更新できない場合、中間テーブルを用意してそっちに一度フラグ内容を入力して、そこから結合させる、といった回りくどい方法しか思いつかなかったのですが、もっと効率的な良い方法はないでしょうか。
できれば一つのSQL文だけでテーブルの更新まで行いたいと思っているのですが、調べてもわからず行き詰まっていました。
もし、ヒントや方向性、参考になるような事例だけでもあればご教示いただけるとありがたいです。

※初心者なので、そもそもの認識や知識が間違っているようでしたらそれもご指摘いただけると大変助かります。

どうぞよろしくお願いいたします。

VBA

1 2Dim db As DAO.Database 3Set db = CurrentDb 4 5Dim mySql As String 6 7mySql = "UPDATE Tab1" 8mySql = mySql & " SET col1 = "選択済"" 9mySql = mySql & " WHERE EXISTS" 10mySql = mySql & " (SELECT TOP 30 * from Tab1" 11mySql = mySql & " WHERE col2 = 1" 12mySql = mySql & " ORDER BY Rnd([主キー]))" 13 14db.Execute mySql, dbFailOnError 15 16------ 17以下の通りサブクエリ内の条件を一部変えて、同様の処理をいくつも続ける 18(SELECT TOP 30 * from Tab1 19WHERE col2 = 2 20ORDER BY Rnd([主キー])) 21 22------ 23242526

補足情報(FW/ツールのバージョンなど)

Access2016

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2020/10/02 10:32

> UPDATEステートメントではサブクエリを使えないらしい、ということが調べてみて分かりました。 一体どこの情報ですか?
sousuke

2020/10/02 12:38

exists句にtop30のorderby rndって何か意味ありますか?existsは基本的にtop1と同等なんであんまり意味ないと思います。
tatsutatsu

2020/10/03 08:17 編集

sazi様 https://teratail.com/questions/122998 https://asai-atsushi.blog.ss-blog.jp/2018-09-04 WHEREで使えないとは書かれていないので、読み違えているのかもしれません。 sousuke様 https://uen1130.hatenadiary.org/entry/20150729/p1 上記参考にして、条件に合致したレコードからランダムに30件抽出したく、このようなコードとしました。こちらもおかしいようですね。。ご指摘ありがとうございます。 もし、代替のコードあればご教示いただければ幸いです。
guest

回答3

0

ベストアンサー

SQL

1UPDATE Tab1 SET col1 = "選択済" 2where

上記のように更新対象が一つのテーブルであれば、where 条件でどのようなサブクエリを使用しても、更新できないクエリーにはなりません。

更新できないクエリーになるのは、主に更新対象を特定できない時です。

サブクエリ内の条件を一部変えて、同様の処理をいくつも続ける

同様な内容であれば問題ないと思います。

追記

UPDATE Tab1 SET col1 = "選択済" where 主キー in ( SELECT TOP 30 主キー from Tab1 WHERE col2 = 2 ORDER BY Rnd(主キー) )

投稿2020/10/02 10:36

編集2020/10/03 08:38
sazi

総合スコア25327

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsutatsu

2020/10/03 07:31

ご回答ありがとうございます。 再度同内容のコードで試してみたのですが、テーブルの全レコードに"選択済"が入力され、WHERE EXISTS〜以降が無視された状態でクエリが実行されているような結果になりました。 何か考えられる原因はあるでしょうか?
sazi

2020/10/03 08:24

> 何か考えられる原因はあるでしょうか? 意図通りの条件になっていないとしか言えません。 質問に書かれているwhere条件の意図が良く分かりませんが、ランダムな主キーに対しての更新という事で追記しました。
sazi

2020/10/03 08:43 編集

質問へのコメントを見てやりたいことが理解出来ましたので、SQLを訂正しておきます。 existsは有無を判断するのですから、目的には合っていません。 主キーを限定するのですから in を使用します。
tatsutatsu

2020/10/03 08:52

何度もありがとうございます。 ご提示いただいたSQLでやりたいことが実現しました。 >existsは有無を判断するのですから、目的には合っていません。  主キーを限定するのですから in を使用します。 こちらの基本理解と、UPDATEでのサブクエリ利用の理解がどちらも低かったためうまくできなかったようです。 もう少し基礎理解をしつつ、SQL実装したいと思います。 とても良い気付きとなりました。ありがとうございます。
sazi

2020/10/03 13:28 編集

existsでも相関でキー参照は可能ですけど、相関ではrnd()で都度複数件する事になりますので、やはり目的には合いません。
tatsutatsu

2020/10/03 16:21

追加でありがとうございます。こちらで理解できました。 何度も本当にありがとうございます! また、是非よろしくお願いします。
guest

0

SQL

1UPDATE Tab1 2SET col1 = "選択済" 3WHERE [主キー] In 4 (SELECT TOP 30 [主キー] from Tab1 5 WHERE col2 = 1 6 ORDER BY Rnd([主キー]))

でいかがでしょうか。

投稿2020/10/03 08:15

kitasue

総合スコア314

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsutatsu

2020/10/03 13:04

回答ありがとうございます。 こちらのSQLで実現しました。 また、機会があればよろしくお願いします。
kitasue

2020/10/03 14:22

回答の編集時刻をご確認くださいね。
tatsutatsu

2020/10/03 16:19

失礼しました。以後確認するようにいたします。
guest

0

UPDATEステートメントではサブクエリを使えないらしい

これは条件によって使えない場合があるという事で今回のWhereに対してのサブクエリなら大丈夫ですよ
参照系のクエリをサブクエリ付で作成してみて表示された値が変更できるかで判断がつくと思います。

ただ今後更新できないクエリの場合なら主キーだけ配列に残して後からまとめて更新という手段もあります。
(ワークテーブルを使いたくない場合)
その場合BeginTrans、CommitTransがキーポイントとなります。

ご参考までに。

追記
【SQL】5分でわかる! EXISTSでサブクエリを扱う方法のように
WHERE EXISTSで親子関係があるならその親子条件を記載しなければなりません。
(この場合親の[主キー]と子の[主キー])

投稿2020/10/02 16:13

編集2020/10/03 07:51
kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsutatsu

2020/10/03 07:41

ご回答ありがとうございます。 先のご回答者様と同様の内容となり恐縮ですが、よろしければご確認お願いいたします。 --------- 再度同内容のコードで試してみたのですが、テーブルの全レコードに"選択済"が入力され、WHERE EXISTS〜以降が無視された状態でクエリが実行されているような結果になりました。 何か考えられる原因はあるでしょうか?
tatsutatsu

2020/10/03 08:12

追記でいただいた親子関係についてですが、今回のコードでは1テーブルしか使用していません。追記いただい内容は複数テーブルを使用している場合、との理解であっているでしょうか?
kuma_kuma_

2020/10/03 08:18 編集

いいえ。同じテーブルでも条件は必要ですよ。 追加クエリとしてではなく参照クエリで一度確認すると判ると思います。 今の状態ですと絞り込みができず全件表示されるはずです。 Select [主キー], col1 From Tab1 WHERE EXISTS (SELECT TOP 30 * from Tab1 WHERE col2 = 1 ORDER BY Rnd([主キー]))
tatsutatsu

2020/10/03 08:35

ありがとうございます。確認してみたところ、ご指摘の通り絞り込みできておらず全件表示されていました。もう少し検討してみます。
kuma_kuma_

2020/10/03 08:39

Select [主キー], col1 From Tab1 AS Tab1_A WHERE EXISTS (SELECT TOP 30 * from Tab1 AS Tab1_B WHERE Tab1_A.[主キー] = Tab1_B.[主キー] AND col2 = 1 ORDER BY Rnd([主キー]))
tatsutatsu

2020/10/03 13:01

改めていただいたSQL試してみましたが、構文エラーとなりうまくいきませんでした。 同じテーブルでも条件には必要とのことでAとBに分けて書かれているのかと思いますが、先に提示いただいたURLでの事例では同一テーブルでの条件書きがなかったので、これらを整理できるまでまだ私の理解が追いついていないようです。もう少し深掘って考えてみます。 何度も返答いただいたのにすべてを理解できず申し訳ありません。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問