未経験で新卒エンジニアをしているものです!
先日案件で、以下のような処理を行うタスクに出会ったので共有いたします。
ゴール
・特定のテーブル(例: tables)のカラム(例:column)に入っている値(例: 000 - 13579 - 0000
)のうち、ハイフン区切り3塊の数字の中央の値が$numberのいずれかの値(例:13579 )と一致している場合、そのレコードをdatabaseから取得する
例:
Itemsテーブル
numberカラム |
---|
000 - 13579 - 0000 |
000 - - 0000 |
13579 - 0000 |
$numberの設定
$number = "13579,24680,31579,424680,513579,624680,713579,824680,913579,102468"
;
処理の流れ
①一塊の値をカンマで区切って配列に格納
(→環境変数[^1]としてnumberを設定する場合も考慮して、一つの文字列を分解する工程を入れています)
②table.columnのうち、'数字-数字-数字'を満たすレコードに絞る
(→NULLや文字が入っている例外を省く)
③中央の値が$numberのいずれかの数値と一致するレコードに絞る
↓↓↓
実装例
/**
* $numberの値を設定
* ※$numberと値と一致しているtable.columnを抽出したい
*/
$number = "13579,24680,31579,424680,513579,624680,713579,824680,913579,102468"
;
/**
* ①一塊の値をカンマで区切って配列に格納
*/
$number = explode(',', $number);
/**
* ②table.columnの中央の値が'数字-数字-数字'を満たす値に絞る
*/
$query = \DB::table('Items');
$query->whereRaw("table.column REGEXP '^[0-9]+-[0-9]+-[0-9]+$'")
/**
* ③table.columnのうち、
* 中央の値が$numberのいずれかの数値に一致する値に絞る
*/
->where(function ($query) use ($number) {
foreach ($number as $value) {
$query->orWhereRaw("SUBSTRING_INDEX(SUBSTRING_INDEX(table.column, '-', 2), '-', -1) = ?", [$value]);
}
});
〜分解して解説〜
REGEXP '^[0-9]+-[0-9]+-[0-9]+$'
↓↓↓
^
:文字開始記号
$
:文字終了記号
[0-9]
:0〜9の数字が入ることを示す
-
:数字間に-が入ることを示す。カンマ区切りの場合は'^[0-9]+,[0-9]+,[0-9]+$'となる。
orWhereRaw
:WHERE へ SQL 文を直接挿入できるメソッド。ここでは、中央の値が特定の値のいずれかと一致する条件を追加。where〜or〜or〜...という条件式ができる
SUBSTRING_INDEX(table.column, '-', 2)
:table.columnの値において、左から2番目の-で2つのブロックに区切った左側の値を出力する(例:000 - 13579 - 0000のうち、000 - 13579)
SUBSTRING_INDEX(SUBSTRING_INDEX(table.column, '-', 2), '-', -1)
:SUBSTRING_INDEX(table.column, '-', 2)の値(例:000 - 13579)において、-で2つに区切ったブロックのうち右から1番目の値を出力する(例:13579)
参考:
https://dev.mysql.com/doc/refman/8.0/ja/string-functions.html#function_substring-index
環境変数*:
https://qiita.com/s_ryota/items/26f1a05737a48ad08956
感想
最初は複雑な処理にビビってしまっていましたが、一つ一つ落ち着いて分解して考えると理解できました!
少しでも参考になれば嬉しいです!