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

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

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

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

2回答

483閲覧

MYSQLのストアドプロシージャでIN区の中を可変にしたい

eleele28

総合スコア18

MySQL

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

1クリップ

投稿2022/03/23 08:52

前提

MySQLでストアドプロシージャを書いています。
「種別ID」をカラムに含むテーブルから、特定の種別IDに一致するレコード群をSelectするプロシージャです。
今現在のプロシージャは種別IDを1つだけ引数としてもらい、当該種別IDに一致するレコードをSelectします。
(引数がnullの場合は、全レコードをselectします。)

実現したいこと

今現在は種別ID1つのみを引数としてもらうプロシージャとなっていますが、
複数個の種別IDに一致するレコード群をSelectできるように改造したいです。

●例
・今
引数として種別ID「2」をもらう⇒「種別ID=2」であるレコードがSELECTされる
・改造後
引数として種別ID「2,3,4」をもらう⇒「種別ID=2 or 3 or 4」であるレコードがSELECTされる

該当のソースコード

今現在のプロシージャ

MySQL

1DELIMITER $$ 2CREATE PROCEDURE `hoge_procedure`( 3 IN param_hoge_type_id INT #検索対象種別ID 4 ) 5#以降にストアドプロシージャの処理を記述する 6BEGIN 7#出力対象の列を指定する 8 SELECT 9 hoge_id #ID抽出 10 11 #データ取得元のテーブルを指定する 12 FROM 13 hoge_table 14 15 WHERE 16 hoge_type_id = IFNULL(param_hoge_type_id, hoge_type_id) #nullがきたら全部を検索するようにする 17 ; 18 19#ストアドプロシージャの処理を終える 20END $$ 21delimiter ;

自分なりの方針

以下の方針でやり方がないか、探しています。
①引数の型を文字列型に変える(引数として「2,3,4」という文字列が与えられる想定)
②Whereの中に条件としてIN()を使い、IN()の中身を引数に応じて設定する

やりたいが都合上できないこと

hoge_tableのhoge_type_id カラムに含まれる値を1,2,3,4,5…の整数ではなく1,2,4,8,16…(2のべき乗)とし、Where条件としてビット演算をすればかんたんに実現できそうですが、カラム自体に格納されている値を変化させるのはシステム他部位への影響が甚大であるため、出来れば行いたくないです。

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

MySQL 5.7.33

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

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

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

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

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

guest

回答2

0

解決してますけど文字列使うのがありならパラメータの区切り文字を前後につけて
種別IDの前後に区切り文字を加えてパラメータで部分一致すればいいです。
IDのような完全一致の複数検索の場合はこの手法でINを使わなくても対応できます。

例えば
引数として種別ID「2,3,4」をもらう⇒パラメータは「,2,3,4,」にする
データの種別IDは「1」の場合⇒「,1,」でパラメータ「,2,3,4,」は部分一致しない
データの種別IDは「2」の場合⇒「,2,」でパラメータ「,2,3,4,」は部分一致する
データの種別IDは「3」の場合⇒「,3,」でパラメータ「,2,3,4,」は部分一致する
データの種別IDは「4」の場合⇒「,4,」でパラメータ「,2,3,4,」は部分一致する
データの種別IDは「5」の場合⇒「,5,」でパラメータ「,2,3,4,」は部分一致しない

SQL

1 2 SELECT 3 hoge_id #ID抽出 4 5 #データ取得元のテーブルを指定する 6 FROM 7 hoge_table 8 9 WHERE 10 ','+IFNULL(param_hoge_type_id,cast(hoge_type_id as varchar(50)))+',' 11 like '%,'+cast(hoge_type_id as varchar(50))+',%' 12

mysql知らないんで適当に書いてます。param_hoge_type_idはコンマ区切りの文字列想定

投稿2022/03/24 05:21

sousuke

総合スコア3828

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

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

eleele28

2022/03/25 04:18

ありがとうございます!!こんな方法もあるんですね。
guest

0

ベストアンサー

testデータ作成

SQL

1create table tbl (id int primary key,val int); 2insert into tbl values(1,1),(2,2),(3,5),(4,4),(5,2); 3select * from tbl where val in(2,3,4);

procedue作成

SQL

1drop procedure if exists proc; 2delimiter // 3create procedure proc(IN args varchar(50)) 4begin 5set @sql='select * from tbl where 1 '; 6if args regexp "^(\\d+,)*\\d+$" then 7set @sql:=concat(@sql,'and val in (',args,')'); 8else 9set @sql:=concat(@sql,'and 0'); 10end if; 11prepare stmt from @sql; 12execute stmt; 13end; 14// 15delimiter ;

※調整:数字の羅列以外はNGとする

procedure実行

SQL

1call proc('2,3,4'); /*出力OK*/ 2call proc('2'); /*出力OK*/ 3call proc('6'); /*ヒットするデータはないがOK*/ 4call proc('x'); /*数値じゃないので戻り値がない*/ 5

投稿2022/03/23 09:09

編集2022/03/23 09:21
yambejp

総合スコア114784

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

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

eleele28

2022/03/24 01:10

ありがとうございます!!
yambejp

2022/03/25 00:18

よく考えたらfind_in_setだけで解決するかもしれません select * from tbl where find_in_set(val,’2,3,4');
eleele28

2022/03/25 04:21

まさに今回のためにあるような関数ですね、ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問