teratail header banner
teratail header banner
質問するログイン新規登録

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

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

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

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

SQL

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

Q&A

2回答

841閲覧

条件を満たす組み合わせを抽出するSQL文

Majespy

総合スコア22

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

SQL

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

0グッド

0クリップ

投稿2022/12/24 05:10

編集2022/12/24 13:34

0

0

前提

任意の条件を満たす商品の組み合わせを抽出したい

実現したいこと

itemsテーブル

idnamepriceweight
1pen10011.5
2note1508.3
3paper_clip401.3
4glue21017.1
5eraser1104.0
6compasses3204.9

■流れ
①条件を選択して検索
└条件はprice「〜円まで」とweight「〜gまで」のいずれか、またはその両方
②①の条件を満たす組み合わせを抽出する
③②の結果からランダムで1つの組み合わせを返す

例1)price「250円まで」, weight「指定なし」
⇨[1, 2], [1, 3, 5], [2, 3], [3, 4], [3, 5]

例2)price「指定なし」, weight「〜12gまで」
⇨[1], [2, 3], [3, 5, 6], [5, 6]

例3)price「250円まで」, weight「〜12gまで」
⇨[1], [2, 3], [3, 5]

お力添え願いたいこと

②のSQL文

手段A.②で組み合わせをSQLで抽出してから、③をLaravelでランダムに抽出する
手段B.②③を同時にSQLで抽出する(技術的に可能?)

参考

サイゼリヤ1000円ガチャ( https://saizeriya-1000yen.marusho.io/ )

試したこと

ORDER BY RAND();でランダムに全件抽出し、抽出結果が条件を満たしているかを判別
満たす:成功
満たさない:もう一度SQLを回す(場合によってはなかなか終わらない)

⇨非常にナンセンスな書き方のため、一発で出せるSQL文はないか気になりご質問させていただきました。

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

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

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

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

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

YT0014

2022/12/24 14:05

ORDER BY RAND()と再帰で作成可能な気がしますが、再帰は各DB毎に異なるので、対象DBをご提示いただいたほうが良いかと。
Majespy

2022/12/25 14:50

回答が付きやすくなるようお気遣いいただき、ありがとうございます。 >再帰は各DB毎に異なるので、対象DBをご提示いただいたほうが良いかと。 →使用しているDBはMySQL8となります。
guest

回答2

0

php

1public function index(Request $request) 2{ 3 $price = $request->price; 4 $weight = $request->weight; 5 6 $items = Item::query() 7 ->when($price, function($q) use ($price) { 8 $q->where('price', '=<', $price); 9 }) 10 ->when($weight, function($q) use ($weight) { 11 $q->where('weight', '=<', $weight); 12 }) 13 ->inRandomOrder() 14 ->get(); 15 16 $results = null; 17 18 if ($items->isNotEmpty()) { 19 $results = $items->pluck('id')->random(random_int(1, $items->count())); 20 } 21 22 dd($results); 23}

投稿2022/12/26 13:52

phper.k

総合スコア3923

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

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

phper.k

2022/12/26 13:59

動作確認はしてないので、細かな修正はご自身で行ってください。
Majespy

2022/12/28 16:11

ご回答ありがとうございます。 when句を除いて実行するとランダムで件数・データが取得できるのですが、when句をいれる(片方のみも試しました)と全てNULLで返ってきました。 この場合、when句の修正が必要という認識でお間違いないでしょうか。
phper.k

2022/12/28 16:17

> when句を除いて実行するとランダムで件数・データが取得できるのですが、when句をいれる(片方のみも試しました)と全てNULLで返ってきました。 何言っているのかわからん
guest

0

②①の条件を満たす組み合わせを抽出する

再帰SQLを利用すると、実現可能です。再帰SQLの構文はDBMSごとに少しずつ異なるので、ここではMySQL8で例3を実装したものを示します。例1や例2はWHERE節の条件式を変更すれば実装可能です。

SQL

1WITH RECURSIVE cte AS ( 2 SELECT id, price, weight, CAST(id AS CHAR) AS combination 3 FROM items 4 WHERE price <= 250 AND weight <= 12 5 UNION ALL 6 SELECT I.id, C.price + I.price, C.weight + I.weight, CONCAT(C.combination, ',', I.id) 7 FROM cte AS C 8 JOIN items AS I ON C.id < I.id 9 WHERE C.price + I.price <= 250 AND C.weight + I.weight <= 12 10) 11SELECT combination FROM cte

投稿2022/12/24 18:23

neko_the_shadow

総合スコア2395

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

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

Majespy

2022/12/25 14:53

ご回答ありがとうございます。 再帰SQLなるものがあるのですね、ただただ勉強不足でした。 大変恐縮ですが、これをEloquentで表現する場合どういった構文になるのでしょうか。 基本となるSQL文(WITH RECURSIVE) と比較しながら理解したいため、 お手数をおかけしますが対象となる構文ちょうだいできませんでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問