0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

〜エンジニア初学者の開発日記〜 八の巻

Posted at

こんにちは、つかさです
今まで数回Laravelのクエリビルダについての記事を投稿してきましたが、1番使う機会も多く便利なWhereについてまとめたいと思います。
whereだけでもかなりのバリエーションがあるので、一緒に理解できるよう頑張っていきましょう!:grin:

前提条件

Usersテーブル

id name email status age created_at updated_at
1 John Doe john@example.com active 22 2024-01-01 10:00:00 2024-01-02 12:00:00
2 Jane Smith jane@example.com active 30 2024-01-03 14:00:00 2024-01-04 16:00:00
3 Mike Brown mike@example.com inactive 55 2024-02-01 08:30:00 2024-02-02 09:45:00
4 SUZUKI Taro trao@example.com inactive 40 2024-02-10 09:30:00 2024-03-02 12:40:00

Postsテーブル

id user_id title content status created_at updated_at
1 1 初めての投稿 これは最初の投稿です。 published 2024-06-01 12:00:00 2024-06-01 12:00:00
2 1 旅行の思い出 先週の旅行について書きました。 draft 2024-06-05 14:30:00 2024-06-06 10:15:00
3 2 Laravelの使い方 Laravelの基本を説明します。 published 2024-06-10 09:00:00 2024-06-10 09:00:00
4 3 今日の出来事 今日は良い一日でした。 published 2024-06-15 18:20:00 2024-06-15 18:45:00
5 5 Vue.jsの基本 Vue.jsの使い方を学ぼう。 draft 2024-06-20 11:10:00 2024-06-21 08:30:00

Where

クエリに対して条件を付与することができる。

シンプルなwhereメソッド

 $users = $userBuilder->where('id', '>', 3)
                     ->get();
  • 第一引数 : カラム名
  • 第二引数 : 比較演算子
  • 第三引数 : 比較する値
演算子 説明 例(Laravel) 変換される SQL
= 等しい where('status', '=', 'active') WHERE status = 'active'
!= / <> 等しくない where('status', '!=', 'inactive') WHERE status != 'inactive'
> より大きい where('age', '>', 18) WHERE age > 18
< より小さい where('age', '<', 65) WHERE age < 65
>= 以上 where('score', '>=', 80) WHERE score >= 80
<= 以下 where('score', '<=', 50) WHERE score <= 50
LIKE 部分一致検索(大文字小文字を区別) where('name', 'LIKE', '%John%') WHERE name LIKE '%John%'
NOT LIKE 一致しない where('email', 'NOT LIKE', '%@gmail.com') WHERE email NOT LIKE '%@gmail.com'
ILIKE 部分一致(PostgreSQLのみ・大文字小文字区別なし) where('title', 'ILIKE', '%laravel%') WHERE title ILIKE '%laravel%'

よく見る$userBuilder->where('id', 10)というのは$userBuilder->where('id', = , 10)を省略したものになります。

And条件

:bulb:whereメソッドを繋げることでAnd条件になります。

連続型
 $userBuilder->where('email',  'like', '%.org')
            ->where('id','<', 10)

また以下のようにも書けます!

配列型
 $userBuilder->where([
    ['email',  'like', '%.org'],
    ['id','<', 10],
])

この2つの結果は同じですが、厳密には行われている処理に違いがあります。
連続型はwhere() を1つずつ適用するのに対し、配列型は配列を受け取り、一括適用します。

Or条件

:bulb:Or条件場合は orWhere メソッドを使います。

$userBuilder->where('email',  'like', '%.org')
            ->orWhere('id','<', 10)

範囲条件

whereBetween / orWhereBetween
$userBuilder->whereBetween('id', [4, 6])->get();

上記の例ではidが4,5,6のレコードが取得できます。

$userBuilder->whereBetween('id', [4, 6])->orWhereBetween('age', [20, 30])->get();

orWhereBetweenは範囲のOr条件になります。

whereNotBetween / orWhereNotBetween
  • Betweenの前にNotをつけることで、指定した条件の否定が適応されます
$userBuilder->whereNotBetween('id', [4, 6])->get();
whereBetweenColumns / whereNotBetweenColumns / orWhereBetweenColumns / orWhereNotBetweenColumns
  • 第一引数に指定したカラムの値が、第二引数で渡すカラムリストの間にあるかの条件を付与
$userBuilder->whereBetweenColumns('weight', [
    'minimum_allowed_weight', 
    'maximum_allowed_weight',
])
id name weight minimum_allowed_weight maximum_allowed_weight
1 Alice 5 3 8
2 Bob 2 3 8
3 Charlie 7 5 10
4 Dave 9 6 9

テーブルに上記のようなデータがあった場合、結果は以下のようになります。

  • Alice: 5 は 3 <= weight <= 8 ✅ 取得
  • Bob: 2 は 3 <= weight <= 8 ❌ 取得されない
  • Charlie: 7 は 5 <= weight <= 10 ✅ 取得
  • Dave: 9 は 6 <= weight <= 9 ✅ 取得

:bulb:or条件否定whereBetweenの時と同様です。

含んでいるか条件

whereIn / orWhereIn
  • 第二引数で指定した値を含んでいるかの条件を付与する事ができます
$userBuilder->whereIn('id', [2, 5, 9])

ちなみに$userBuilder->whereIn('id', [2, 5, 9])$userBuilder->where('id', 2)->orWhere('id', 5)->orWhere('id', 9)のショートカット版という覚え方でも良い:ok_hand:

whereNotIn / orWhereNotIn
  • whereInの反対の条件になります
$userBuilder->whereNotIn('id', [2, 5, 9])

whereInメソッドに指定する値は、完全一致でなければならないことに注意!

NULL判別条件

whereNull / orWhereNull
  • 指定したカラムの値がnullであるかどうかの条件になります
$userBuilder->whereNull('email')
whereNotNull / orWhereNotNull
  • whereNullの反対の条件になります
$userBuilder->whereNotNull('email')

日時条件

whereDate / orWhereDate
  • 日付の条件になります
$userBuilder->whereDate('created_at', '<', '2024-01-30')
whereMonth / orWhereMonth
  • 月の条件になります
$userBuilder->whereMonth('created_at', '=', 1)
whereDay / orWhereDay
  • 年度や月を指定せず、シンプルな日付の条件になります
$userBuilder->whereDay('created_at', '=', 12)
whereYear / orWhereYear
  • 年の条件になります
$userBuilder->whereYear('created_at', '=', 2024)
whereTime / orWhereTime
  • 時間の条件になります
$userBuilder->whereYear('created_at', '=', 2024)
whereColumn / orWhereColumn
  • 2つのカラムを比較する条件になります
$userBuilder->whereColumn('created_at', '=', 'updated_at')
問題 ちなみに上記のクエリはどのようなユーザーを取得しようとしているでしょうか?
答え まだ一度も編集や更新をしていないユーザーです。何故ならユーザー作成時にcreated_atとupdated_atには同じ時間が代入されます。その後、更新処理があればupdated_atの時間だけが更新されていきます。

ちなみに比較の条件は複数指定できます。

$userBuilder->whereColumn([
    ['email_verified', '>', 'updated_at'],
    ['created_at', '<', 'updated_at']
])

存在条件

Where Exists
  • サブクエリが 結果を返す場合に true となる条件です
$userBuilder->whereExists(function (Builder $query) {
                  $query->select(DB::raw(1))
                        ->from('posts')
                        ->whereColumn('posts.user_id', 'users.id');
            })

上記の条件を言語化すると以下になります。
「少なくとも1つの投稿(posts)を持つユーザー(users)だけを取得する」という条件

SELECT * FROM users
WHERE EXISTS (
    SELECT 1 FROM posts
    WHERE posts.user_id = users.id
);

ちなみにこのようなクエリを書くことはできません。
$userBuilder->whereExists('posts.user_id', '=', 'users.id'); // ❌ NG
whereExists() の引数には 関数(サブクエリビルダー) しか使えません。

JSON型のカラムに対する条件

whereJsonContains / orWhereJsonContains
  • 配列だった場合
rolesの配列
["admin", "editor", "user"]
$userBuilder::whereJsonContains('roles', 'editor')->get();
SELECT * FROM users WHERE JSON_CONTAINS(roles, '"editor"');

この例では、editorがrolesカラムのjosn型の値にある場合は取得するようなクエリになります。

  • オブジェクトだった場合
rolesのオブジェクト
{
  "features": {
    "newsletter": true,
    "beta": false
  }
}

User::whereJsonContains('features->newsletter', true)->get();
select * from `users`
where json_extract(`features`, '$.newsletter') = true;
whereJsonLength / orWhereJsonLength
  • JSON カラム内の配列の要素数を条件になります
rolesの配列
["PHP", "Laravel", "MySQL"]
User::whereJsonLength('skills', 3)->get();
select * from `users`
where json_length(`skills`) = 3;

まとめ

読んでいただきありがとうございました!
これからも自分のペースで記事を更新したり、新たな記事を書いていこうと思うので是非見ていただけたらなと思います!:grin:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?