暇なときに予定を探せるアプリyoteiPickerをリリースしました。
Laravelのクエリビルダで複数のカラムをグループ化させる方法を解説します。
バージョンは6系です。
ブログで以下の記事も書いているので、ぜひチェックしてください!
>>フリーランスも対象!エンジニア転職におすすめなサイト5選
ゴール
user_idとpost_nameでグループ化させる
post_id | user_id | post_name |
---|---|---|
1 | 1 | カレー |
2 | 2 | ちゃんこ |
3 | 3 | チャーハン |
4 | 1 | オムライス |
5 | 2 | ちゃんこ |
↓
user_id | post_name |
---|---|
1 | オムライス |
1 | カレー |
2 | ちゃんこ |
3 | チャーハン |
複数のカラムをグループ化させる時の注意点
よくありがちなのが、
user_id | post_name |
---|---|
1 | オムライス,カレー |
2 | ちゃんこ |
3 | チャーハン |
のようにできると考えてしまうことです。
post_nameにオムライス、カレーのように複数の項目を入れることはできません。
user_idとpost_nameでグループ化させているので、
①user_id→1,1,2,2,3でグループ化
=>1,2,3
②post_name→オムライス、カレー、ちゃんこ、ちゃんこ、チャーハンでグループ化
=>オムライス、カレー、ちゃんこ、チャーハン
ただ、オムライスはuser_id→1、カレーはuser_id→1なので、別々の項目としてデータを取得します。
よって①と②により、
user_id | post_name |
---|---|
1 | オムライス |
1 | カレー |
2 | ちゃんこ |
3 | チャーハン |
となるわけです。
サンプルコード
モデルにデータ取得のロジック、コントローラーに変数格納してビューに変数をわたし、ビューでforeachを用いてデータを表示させていきましょう。
モデル(Post.php)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;←忘れずに追加するこれでDB::使用可能
class Post extends Model
{
public function getResult()
{
// user_id,post_nameでグループ化
return DB::table('posts')
->select('user_id', 'post_name')
->groupBy('user_id', 'post_name')
->get();
}
}
コントローラー(PostController.php)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;←バージョン8系なら use App\Models\Post;
class PostController extends Controller
{
public function index()
{
$this->posts = new Post();
$results = $this->posts->getResult();
return view('posts.index', compact(
'results',
));
}
}
ビュー(index.blade.php)
<table>
<thead>
<tr>
<th>ユーザーID</th>
<th>ネーム</th>
</tr>
</thead>
<tbody>
@foreach ($results as $result)
<tr>
<td>{{ $result->user_id }}</td>
<td>{{ $result->post_name }}</td>
</tr>
@endforeach
</tbody>
</table>
エラーになるやつ
return DB::table('posts')
->select('user_id', 'post_name')
->groupBy('user_id')
->get();
冒頭に解説した、user_idでまとめようとすると、post_nameが一部の項目で複数になってしまうのでエラー起きます。
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'tests.posts.post_name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by (SQL: select `user_id`, `post_name` from `posts` group by `user_id`)
こんなエラー起きると思います。
簡単に言えば、“GROUP BY” で指定していないカラムが “SELECT” に入っているです。
group byでハマると抜け出すの大変なので、最初のうちは慣れるまで今季強う戦う必要がありますね。
今回はここまでです。他にもクエリビルダについて解説しています。
参考になりましたら、LGTMまたは記事のストックをお願いいたします。
ブログで以下の記事も書いているので、ぜひチェックしてください!
暇なときに予定を探せるアプリyoteiPickerをリリースしました。