1. 程式人生 > 其它 >MYSQL-group by 用法解析

MYSQL-group by 用法解析

技術標籤:資料庫phpEloquentmysqlgroup by

MYSQL-group by 用法解析

group by 用法

​ group by語法可以根據給定資料列的每個成員對查詢結果進行分組統計,最終得到一個分組彙總表。
SELECT子句中的列名必須為分組列或列函式。列函式對於GROUP BY子句定義的每個組各返回一個結果。
某個歷史觀影進度記錄表結構和資料如下:
在這裡插入圖片描述

例如,我想列出每個人的最新一條觀影記錄,sql語句如下:

SELECT user_id, MAX(updated_at) AS MAXIMUM
FROM movie_histories
GROUP BY user_id;

查詢結果如下:
在這裡插入圖片描述
解釋一下這個結果:

  • 1、滿足“SELECT子句中的列名必須為分組列或列函式”,因為SELECT有GROUP BY user_id中包含的列user_id。
  • 2、“列函式對於GROUP BY子句定義的每個組各返回一個結果”,根據使用者分組,對每個使用者返回一個結果,就是每個使用者的最後觀影時間。
    注意:計算的是每個使用者(由 GROUP BY 子句定義的組)而不是整個表的 MAX(updated_at)。

將 WHERE 子句與 GROUP BY 子句一起使用

分組查詢可以在形成組和計算列函式之前使用where篩選記錄。必須在GROUP BY 子句之前指定 WHERE 子句。

例如,查詢使用者今日每個電影的最近觀影時間

select movie_id,user_id,MAX(updated_at) 
from `movie_histories`
where `created_at` > '2020-12-17 00:00:00)'
group by `movie_id` ,`user_id`;

查詢結果如下:
在這裡插入圖片描述
查詢結果如下:

注意:在SELECT語句中指定的每個列名也在GROUP BY子句中提到。未在這兩個地方提到的列名將產生錯誤。
GROUP BY子句對movie_id,user_id的每個唯一組合各返回一行。

在GROUP BY子句之後使用HAVING子句

  1. where條件會在分組和聚集前執行,having在分組後執行

  2. where直接針對資料庫欄位進行篩選,having可以根據聚合函式進行篩選(也可針對欄位進行過濾,但是需要先select該欄位)
    例如:尋找今日數超過2個的部門的最高和最低薪水:
    例如:尋找觀看電影數量超過2部的使用者

select movie_id,user_id,MAX(updated_at) 
from `movie_histories`
group by `movie_id` ,`user_id`
having count(*)>2;

查詢結果如下:
在這裡插入圖片描述

需求例項:

電影記錄表movie_history是根據劇集來記錄的使用者瀏覽記錄,以便使用者挑選了多集觀看時,能記錄每一集的觀看進度。也就是在表記錄中,[user_id,movie_id,series_id]才是一組唯一鍵;
但是這裡需要定位使用者最近一次觀看某部電影的進度記錄;
這裡的就需要根據movie_id來分組,但是分組之後,SELECT子句中的列名必須為分組列或列函式,就無法查詢整條資料記錄,這裡的一個方法是使用where in 來實現。

select * from movie_histories
where (movie_id,updated_at)
in (
  select movie_id ,max(updated_at) 
  from `movie_histories`
  where `user_id`= 450
  group by `movie_id`
  );

對應的Eloquent查詢為:

MovieHistory::whereIn(DB::raw('(movie_id,updated_at)'),function ($query)use($user) {
                    $query->select('movie_id',DB::raw('max(updated_at)'))
                        ->from('movie_histories')
                        ->where('user_id', $user->id)
                        ->groupBy('movie_id');
                }
            );