idiormを使っていて取り出したデータに対して、CASE式を使って条件付けで並び替えをしたい場合、
どうしたら良いか調べても見つからなかったので、まとめてみました。
例として、以下のような商品テーブルがあったとします。
■商品テーブル(テーブル名:item_table)
id | category_id | name | price | stock |
---|---|---|---|---|
1 | 1 | 商品1 | 1000 | 0 |
2 | 1 | 商品2 | 2000 | 1 |
3 | 2 | 商品3 | 3000 | 0 |
4 | 2 | 商品4 | 1000 | 0 |
5 | 2 | 商品5 | 1000 | 3 |
■各カラムの説明
id:商品ID
category_id:商品が属しているカテゴリーのID
name:商品名
price:価格
stock:在庫数
この商品テーブルを、カテゴリーIDが"2"で、売り切れ(在庫数はが0)の商品は、
他の商品よりも後に取得したいといった場合、以下の方法で取得できます。
$items = ORM::for_table('item_table')
->select('name')
->orderByExpr('CASE WHEN category_id = 2 AND stock = 0 THEN 0 ELSE 1 END DESC')
->findArray();
取得できる配列
array(5) {
[0]=>
array(1) {
["name"]=>
string(7) "商品1"
}
[1]=>
array(1) {
["name"]=>
string(7) "商品2"
}
[2]=>
array(1) {
["name"]=>
string(7) "商品5"
}
[3]=>
array(1) {
["name"]=>
string(7) "商品3"
}
[4]=>
array(1) {
["name"]=>
string(7) "商品4"
}
}
また、上記方法で並び替えたデータに対して、価格の昇順で並び替えを行いたい場合、
orderByExpr
の記述の後に通常のorderByAsc
を追加してあげると対応できます。
$items = ORM::for_table('item_table')
->select('name')
->select('price')
->orderByExpr('CASE WHEN category_id = 2 AND stock = 0 THEN 0 ELSE 1 END DESC')
->orderByAsc('price')
->findArray();
取得できる配列
array(5) {
[0]=>
array(2) {
["name"]=>
string(7) "商品1"
["price"]=>
int(1000)
}
[1]=>
array(2) {
["name"]=>
string(7) "商品5"
["price"]=>
int(1000)
}
[2]=>
array(2) {
["name"]=>
string(7) "商品2"
["price"]=>
int(2000)
}
[3]=>
array(2) {
["name"]=>
string(7) "商品4"
["price"]=>
int(1000)
}
[4]=>
array(2) {
["name"]=>
string(7) "商品3"
["price"]=>
int(3000)
}
}
意外と使う機会もありそうなので、誰かのお役に立てれば幸いです。