従業員とグループのテーブルの間には、多対多の関係があります。ピボットテーブルを作成しましたが、すべて正しく動作しています。しかし、従業員テーブルにsortOrder列があり、それを使用して、それらが表示される順序を決定しています。 sortOrder列の値が1の従業員が最初になり、2の値が2番目になるというようになります。 (または降順でソートされている場合は逆)sortOrder列は、null値を許可する整数列です。
従業員を並べ替え列で並べ替えるようにグループモデルを設定しましたが、問題が発生しました。 null値は常に最初に表示されます。通常の "asc"または "desc"の代わりにISNULLおよび同様のSQLメソッドを使用しようとしましたが、エラーしか表示されません。
これが私のグループモデルのコードです。
class Group extends Eloquent {
public function employees()
{
return $this->belongsToMany("Employee")->orderBy('sortOrder', 'asc');
}
}
そして、これがモデルにアクセスするためにコントローラーで使用するものです:
$board = Group::find(6)->employees;
NULL値を最後にソートするためのLaravelのトリックは何ですか?
public function employees()
{
return $this
->hasMany('Employee')
->select(['*', DB::raw('IF(`sortOrder` IS NOT NULL, `sortOrder`, 1000000) `sortOrder`')])
->orderBy('sortOrder', 'asc');
}
説明:
IFステートメントは、ここで問題を解決します。 NULL値が見つかった場合、代わりに大きな数値がsortOrderに割り当てられます。 NULL値でない場合は、実際の値が使用されます。
LaravelはISNULL
メソッドを考慮していませんが、IF
ステートメントよりも効率的であり、結果は同じままなので、生のクエリとして渡して使用することができます。次のように、1000000人の従業員(受け入れられた回答)を超える場合:
public function employees()
{
return $this->hasMany('Employee')
->orderBy(DB::raw('ISNULL(sortOrder), sortOrder'), 'ASC');
}
Update:orderByRaw() メソッドを使用することもできます:
public function employees()
{
return $this->hasMany('Employee')
->orderByRaw('ISNULL(sortOrder), sortOrder ASC');
}
マイナス記号をフィールドに追加し、順序をDESCに変更するだけです。
$q->orderBy(\DB::raw('-`sortOrder`'), 'desc');
Laravel 5.2以降では、単にorderByRaw
を呼び出します。列ではなく、集計された値を並べ替えることもできます。次の例ではmax_st
は、サブモデルがない場合はnull
になります。
Model::where('act', '2')
->leftJoin('submodels', 'model.id', '=', 'submodels.model_id')
->select('models.*', DB::raw('MAX(submodels.st) as max_st')),
->orderByRaw('max_st DESC NULLS LAST');
任意の大きな数に依存する代わりに、次のことも実行できます。
public function employees()
{
return $this
->hasMany('Employee')
->select(['*', DB::raw('sortOrder IS NULL AS sortOrderNull')])
->orderBy('sortOrderNull')
->orderBy('sortOrder');
}
SQLiteによってサポートされるという追加の利点があります。
私は最近、Laravel 5.6を使用してこの問題に遭遇しました。ここで、junkystuの回答が完璧でした。ただし、テストフレームワークはsqliteを使用しているため、テストは常に500エラーを返しました。
これは私たちが思いついたものであり、DBドライバーに少し依存しているはずです。
昇順
$query->orderBy(DB::raw('column_to_sort IS NULL, column_to_sort'), 'asc');
降順
$query->orderBy(DB::raw('column_to_sort IS NOT NULL, column_to_sort'), 'desc');
PostgreSQLの回避策
数値型の場合:
DB::table('t')
->select(['id', 'val'])
->orderBy(DB::raw("coalesce(val, 0)"), 'desc')
テキストタイプの場合:
orderBy(DB::raw("coalesce(val, '')"), 'desc')
トリックは、通常の整数(またはテキスト)値としてソートできるように、ソート列のNULL
値をゼロ(または空の文字列)に置き換えることです。