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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

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

Q&A

解決済

4回答

1413閲覧

多対多の親子関係のテーブルから子供のデータの組み合わせで検索したい。

GOROGORO

総合スコア66

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

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

0グッド

0クリップ

投稿2019/07/09 01:41

編集2019/07/09 01:42

こんにちは。

以下のような多対多構造のテーブルがあったときの質問です。

【テーブル構造】
test_cases
・id
・name

test_case_test_conditions
・id
・test_cases_id
・test_condition_id

test_conditions
・id
・name

【その他の前提】
このとき、アプリケーション側の仕様として、
test_casesに対してtest_case_test_conditionsの組み合わせを一意とします。

ex.
OKパターン
test_case_test_conditions

idtest_cases_idtest_condition_id
111
212
321

NGパターン
test_case_test_conditions

idtest_cases_idtest_condition_id
111
212
321
422

【質問】
SQLで以下の条件のデータを取得するにはどのようにしたら良いでしょうか?
1.指定したtest_conditionの組み合わせがすでに存在するか?
2.指定したtest_conditionをすべて持つtest_conditonをselectする。
ex: test_conditon_id[1,2]が指定されたときに、test_condition_id[1,2][1,2,3]や[1,2,4]など指定したtest_conditon以上の条件で絞り込みたい。
3.指定したtest_conditionの一部のみを持つtest_conditonをselectする。
ex: test_conditon_id[1,2,3]が指定されたときに、test_condition_id[1,2,3][1,2]や[1][2][3]など指定したtest_conditon以下の条件で絞り込みたい。[1,4]など指定していないtest_conditon_idを持つものは除外したい。

指定したtest_conditionはアプリケーション側から動的に指定されます。
複雑なSQLとなり、困惑して思考停止気味です。。。

アイデアが思いついた方、お手数ですがアドバイスいただけると幸いです。

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

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

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

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

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

yambejp

2019/07/09 01:48

「test_casesに対してtest_case_test_conditionsの組み合わせを一意」という命題に対して OKパターンでも一意になっているように見えませんが どういうロジックか明確にしてもらえませんか?
yukikp

2019/07/09 01:50

test_cases_id => test_condition_idの組み合わせで、 1 => 1 1 => 2 2 => 1 がOKパターンで 1 => 1 1 => 2 2 => 1 2 => 2 がNGパターンという意味がよく分からないです。
sazi

2019/07/09 02:23 編集

OKパターンが 1 => 1 1 => 2 2 => 2 なら、組み合わせとして重複しないという意味で理解はできますけどね
m.ts10806

2019/07/09 02:42

>複雑なSQLとなり 「複雑なSQLであれば対応可能」とも取れますが、実際はどうなのでしょうか。 もちろんパフォーマンスなども考慮したいというのでしたらその方向でのアドバイスがあるかもしれませんが、実際のところ現在の質問内容からは判断しかねる部分です
GOROGORO

2019/07/09 04:56

コメントありがとうございます。 回答させていただきます。 ** 組み合わせを一意 ** についてですが、 1 => 1 1 => 2 というレコードがあっても、 2 => 1や 3 => 2や 4 => 1 4 => 2 4 => 3 はOKとしたいが、 5 => 1 5 => 2 といった一つのtest_cases_idの中に属するtest_condition_idの組み合わせが同じな場合はNGとしたい。という意図です。 test_condition_idの組み合わせが一部不足していたり、それ以上のものが指定されていたらOKということです。 また、データ登録時にこれらのOK,NGを判定してinsertやupdateを切り替えるような処理を作りたいと考えています。 分かりづらく申し訳ございません。
m.ts10806

2019/07/09 04:58

質問は編集できますので適宜、追記いただければと。
GOROGORO

2019/07/09 04:59

** 複雑なSQLとなり ** はい。もちろんパフォーマンスにも考慮できたSQLとしたいです。 ただ、今現在どのような構文だったら正常に動作するかもわかっておらず。。。 ひとまずはどのようなデータ取得の方法があるのか、アドバイスいただければ、。。という状況です。 コメントありがとうございます。
yambejp

2019/07/09 05:01

test_cases_idごとにtest_condition_idの組み合わせが完全に同等のものをNGとするのですね? その場合度のタイミングでチェックしてどう弾くのでしょうか 1,1、1,2が登録されていて2,1はOKで2,2が登録されようとした瞬間はじく? でも実は2,1、2,2、2,3かもしれないでしょ?
GOROGORO

2019/07/09 06:34

コメントありがとうございます。 はい。登録時はアプリケーション側でtest_casesを登録する前に、そのtest_casesに紐づくconditionの組み合わせがDBに存在するかをチェックしてから登録処理を流したいと考えています。
guest

回答4

0

ベストアンサー

group_concatでパターンを生成し、登録しようとするパターンがあるかどうかをチェックする。

SQL

1select count(*) 2from ( 3 select test_cases_id, group_concat(test_condition_id order by test_condition_id) pattern 4 from test_case_test_conditions 5 group by test_cases_id 6) test 7where pattern='1,2,3' -- '1,2,3は登録しようとするパターン

※count(*)>1ならパターンが存在

投稿2019/07/09 07:41

編集2019/07/09 07:50
sazi

総合スコア25184

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

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

0

プロシージャとトランザクションを使った例

  • 初期データ

SQL

1create table test_case_test_conditions(id int primary key auto_increment,test_case_id int,test_condition_id int,unique(test_case_id,test_condition_id)); 2insert into test_case_test_conditions(test_case_id,test_condition_id) values(1,1),(1,2),(2,1),(3,1),(3,3),(4,1),(4,2),(4,4);
test_case_idtest_condition_id
11,2
22
31,3
41,2,4
  • procedure作成

SQL

1drop procedure if exists test; 2delimiter // 3create procedure test(IN flg tinyint) 4begin 5if flg=1 then 6commit; 7else 8rollback; 9end if; 10end 11// 12delimiter ;

※引数が1だったときだけcommitする、それ以外はrollback

  • test1

5:1,2を挿入してみる

SQL

1start transaction; 2set @a=0; 3insert ignore into test_case_test_conditions(test_case_id,test_condition_id) values(5,1),(5,2); 4select count(*) as cnt into @a from( 5select test_case_id,group_concat(test_condition_id order by test_condition_id asc) as conditions 6from test_case_test_conditions 7group by test_case_id 8) as t1 group by conditions order by cnt desc limit 1; 9call test(@a);

※挿入されない(test_case_id=1と同値のため)

  • test2

6:2を挿入してみる

SQL

1start transaction; 2set @a=0; 3insert ignore into test_case_test_conditions(test_case_id,test_condition_id) values(6,2); 4select count(*) as cnt into @a from( 5select test_case_id,group_concat(test_condition_id order by test_condition_id asc) as conditions 6from test_case_test_conditions 7group by test_case_id 8) as t1 group by conditions order by cnt desc limit 1; 9call test(@a);

※挿入される

  • test3

7:1,2,3を挿入してみる

SQL

1start transaction; 2set @a=0; 3insert ignore into test_case_test_conditions(test_case_id,test_condition_id) values(7,1),(7,2),(7,3); 4select count(*) as cnt into @a from( 5select test_case_id,group_concat(test_condition_id order by test_condition_id asc) as conditions 6from test_case_test_conditions 7group by test_case_id 8) as t1 group by conditions order by cnt desc limit 1; 9call test(@a);

※挿入される

投稿2019/07/10 02:57

yambejp

総合スコア114814

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

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

0

こんな感じで、test_condition_idの組み合わせチェックはできるかな?

SELECT
COUNT(*)
FROM
(
SELECT
GROUP_CONCAT( test_condition_id ORDER BY test_condition_id ) AS test_condition_id_group
FROM
test_case_test_conditions
GROUP BY
test_cases_id
) test_condition_set
WHERE
//'%1,2%'だ11,21も選ばれるため場合分けしてる。
//上でtest_condition_idの順にGROUP_CONCATさせてるので、1と2は入れ替えなくていいはず。
test_condition_id_group LIKE '1,2'
OR
test_condition_id_group LIKE '%,1,2'
OR
test_condition_id_group LIKE '1,2,%'
OR
test_condition_id_group LIKE '%,1,2,%'

投稿2019/07/09 07:57

yukikp

総合スコア797

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

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

0

皆様ありがとうございました!頂いたアドバイスを元に進みそうです!ありがとうございました!

投稿2019/07/10 03:01

GOROGORO

総合スコア66

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問