【Laravel 쿼리 빌더】DATE_FORMAT한 날짜로 groupBy하는 방법

Laravel 쿼리 빌더에서 날짜별로 그룹화하여 데이터를 검색하는 방법에 대해 설명합니다.

Laravel의 버전은 6 계열입니다.

블로그에서 다음과 같은 기사도 쓰고 있습니다.

목표



이번 목표는 이런 느낌입니다.
posts 테이블을 날짜별로 그룹화하여 amount를 집계

posts 테이블


post_id
amount
created_at


1
100
2021-06-01 12:23:07

2
200
2021-06-01 15:23:23

3
300
2021-06-01 16:21:12

4
400
2021-07-21 19:23:32





created_at
amount


2021/06/01
600

2021/07/21
400


사고방식으로는
· DATE_FORMAT에서 2021-06-01 추출
· 날짜를 그룹화
· amount를 SUM으로 집계하여 데이터 얻기

그럼 가자.



먼저 데이터베이스에 필요한 정보를 넣자.

모델에 데이터 취득의 논리를 쓰고, 컨트롤러에는 변수를 뷰에 건네주고, 뷰에서 foreach로 데이터를 취득하는 흐름입니다.

모델 (Post.php)
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;←記述を忘れない

class Post extends Model
{
    public function getAmount()
    {
      return DB::table('posts')
              ->selectRaw('DATE_FORMAT(created_at, "%Y%m%d") AS date')
              ->selectRaw('SUM(amount) AS total_amount')
              ->groupBy('date')
              ->get();
    }
}

우선, DB::table나 DB::raw를 사용할 수 있도록, 처음에 use Illuminate\Support\Facades\DB; 를 기술합시다.
selectRawselect(DB::raw)의 약어입니다. DATE_FORMAT 함수를 사용하는 경우는, select(DB::raw('DATE_FORMAT()')) 라고도 쓸 수 있습니다만, selectRaw 로 단축할 수 있습니다.

덧붙여서 DATE_FORMAT나 SUM 함수 등은 DB::raw('DATE_FORMAT()')와 DB::raw를 세트로 사용할 필요가 있습니다.
DATE_FORMAT(created_at, "%Y%m%d") 에서 2021-06-01 12:34:32 을 20210601로 변환합니다. 이제 날짜를 그룹화할 수 있습니다.
왜냐하면 날짜가 일치하더라도 시간이 12시와 14시에 다르면 다른 그룹으로 판별되기 때문입니다.
SUM(amount) 에서 amount를 집계할 수 있습니다.

마지막으로 groupBy로 날짜를 그룹화합니다.DATE_FORMAT(created_at, "%Y%m%d"는 AS date와 별칭으로 바뀌므로 date로 그룹화할 수 있습니다.

컨트롤러 측 (postController.php)
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;←忘れない(バージョン6の場合)
// use App\Models\Post;バージョン8以降はこっち書く

class PostController extends Controller
{
    public function index()
    {
        $this->posts = new Post();
        $results = $this->posts->getAmount();

        return view('test.index', compact(
            'results',
        ));
    }
}


뷰(index.blade.php)
<table>
    <thead>
      <tr>
        <th>日付</th>
        <th>合計金額</th>
      </tr>
    </thead>
    <tbody>
    @foreach ($results as $result)
      <tr>
        <td>{{ date('Y/m/d', strtotime($result->date)) }}</td>
        <td>{{ $result->total_amount }}</td>
      </tr>
    @endforeach
    </tbody>
</table>

뷰에 건네받은 $results 에는 취득한 데이터가 포함되어 있습니다.
그래서 foreach로 데이터를 얻을 수 있습니다.
$result->date 하지만 좋지만, 20210601 이 될 것입니다.
이것은 조금 기분 나쁘기 때문에 date 함수와 strtotime을 사용하여 date('Y/m/d', strtotime($result->date))
이제 20210601→2021/06/01이 됩니다.
참고로 date('Y年m月d日', strtotime($result->date)) 라고 쓰면 2021년 6월 1일로 표시됩니다.

실제 출력 화면



groupBy의 주의점



이번에는 날짜별로 그룹화했지만 그룹화에는 주의점이 있습니다.


post_id
이름
created_at


1
aaa
2021-06-01 12:23:07

2
aaa
2021-06-01 15:23:23

3
ccc
2021-06-01 16:21:12

4
ddd
2021-07-21 19:23:32


예를 들어, 날짜별로 그룹화할 때 이름도 선택하고 싶다면 이것은 오류입니다.

왜냐하면, 2021-06-01 aaa, ccc가 되기 때문입니다.
name 열에 두 개의 데이터를 선택할 수 없습니다.

name도 그룹화하고 싶다면
groupBy ( 'date', 'name') 두 가지를 선택하면,

2021-06-01 aaa
2021-06-01 ccc
2021-07-21 ddd

이런 식으로 데이터를 얻을 수 있습니다.

좋은 웹페이지 즐겨찾기