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

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

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

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

Firebird

Firebirdは、オープンソースのリレーショナルデータベース管理システムです。オープンソースとしてBorland社が公開したInterBaseから派生したもので、MGAによる高度なトランザクション管理機能を持ちます。

Q&A

解決済

2回答

6922閲覧

【SQL/Update】更新データの抽出条件に「SELECT結果のある値がすべてxxなら」という表現を組み込みたいです。

tea-leaf

総合スコア8

SQL

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

Firebird

Firebirdは、オープンソースのリレーショナルデータベース管理システムです。オープンソースとしてBorland社が公開したInterBaseから派生したもので、MGAによる高度なトランザクション管理機能を持ちます。

0グッド

0クリップ

投稿2019/02/25 16:34

編集2019/02/26 10:39

AテーブルはAのID(以下AID)、Aのステータス(以下Aステータス)のカラムを持ちます。
BテーブルはBのID(以下BID)、AID、Bのステータス(以下Bステータス)のカラムを持ちます。
AとBは1:Nの関係にあります(ヘッダと明細の関係)。
BのAIDはAのAIDを参照しています。
RDBMSはFirebirdです。

このとき、
A.AID = B.AID かつ B.Bステータスがすべて「完了」であれば、
A.Aステータスを「完了」に更新するというSQLを組みたいです。

下記パターン1・2まではSQLを作成したのですが、
"B.Bステータスがすべて「完了」であれば"という条件をどう表現すれば良いか分かりません。
どのようなSQLにすれば良いか教えてください。
B.Bステータスの値は「完了」以外にもいくつかあるため、すべて「完了」になった時点で
親テーブルであるAのAステータスを「完了」としたいです。

■パターン1

SQL

1Update A 2Set A.ステータス = '完了' 3From B 4Where A.AID = B.AID

■パターン2

SQL

1Update A 2Set A.ステータス = '完了' 3WHERE EXISTS 4( 5Select 1 From B 6Where A.AID = B.AID 7)

宜しくお願い致します。

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

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

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

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

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

Orlofsky

2019/02/25 17:08

質問にCREATE TABLE文と数件で良いからテーブルに存在するデータをINSERT文で提示すると適切なコメントが付き易いです。
sazi

2019/02/26 01:35

Bステータスの取りうる値は限定されていますか? その場合はどのような値でしょう?
guest

回答2

0

mysql的な書き方だとこんなふうにいけます

  • 元データ

SQL

1create table tbl_a (aid int unique,status varchar(10) default ''); 2insert into tbl_a values(1,''),(2,''),(3,''); 3create table tbl_b (bid int unique,aid int,status varchar(10) default ''); 4insert into tbl_b values(1,1,''),(2,1,''),(3,1,''),(4,2,'完了'),(5,2,'完了'),(6,2,'完了'),(7,3,'完了'),(8,3,''),(9,3,'');
  • 更新

SQL

1insert into tbl_a(aid) 2select aid from tbl_b 3group by aid 4having sum(status='完了')=count(aid) 5on duplicate key update status='完了'

投稿2019/02/26 01:03

yambejp

総合スコア114819

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

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

sazi

2019/02/26 01:38 編集

mysqlだとupdateよりも回答の内容の方がメリットあるんでしょうか?
yambejp

2019/02/26 01:52

基本的にリレーションさせるよりバルクで流し込むほうが 構造も単純だし高速化しやすいという意図です。 もちろんFireBirdがなんらかのバルク処理ができるなら それに合わせて書き換える必要はあるでしょうね できないならリレーションしてもいいでしょう
sazi

2019/02/26 02:09

status!='完了`の条件だと件数次第では正のが出せない場合もありそうですよね。 statusのパターンが固定なら問題ないですけど、そうでない場合は、yambejpさんの回答のような条件の取り方の方が高速かもしれません。
tea-leaf

2019/02/26 10:29

saziさん、yambejpさん 質問が2回目で慣れていないこともあり、諸々稚拙な内容であったかと思いますが、ご意見くださり有難うございました。 Firebirdで使用不可の関数やmysqlのケースなど、知らなかったことを勉強できました。
guest

0

ベストアンサー

この手のSQLではEXISTS句を使うケースが多いですが、
ちょっと感覚的に難しいと思うので簡単な方法で。

副問い合わせで完了以外をカウントしたときに0だったらいいので、
以下のようになります。

SQL

1UPDATE A 2SET A.STATUS = '完了' 3WHERE A.AID = 4( 5 SELECT AID FROM 6 ( SELECT B.AID, COUNT(B.BID) AS count FROM B WHERE B.STATUS != '完了' GROUP BY AID ) 7 WHERE count = 0 8)

EXISTS句を使う場合はこのようになります。

SQL

1UPDATE A 2SET A.STATUS = '完了' 3WHERE NOT EXISTS 4( 5 SELECT 1 FROM B WHERE B.STATUS != '完了' AND B.AID = A.AID 6)

投稿2019/02/25 23:20

編集2019/02/25 23:26
mackerel6.023

総合スコア317

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

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

tea-leaf

2019/02/26 10:25

mackerel6.023さん 教えて頂いたクエリで解決しました。 大変助かりました。 "不要なレコードのSELECT結果が存在しなければ"という抽出方法、いろいろなところで応用できそうで勉強になりました。 有難うございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問