MySQL零散拾遗(五)---- 对 GROUP BY 要点进行详细介绍

发布于:2024-07-23 ⋅ 阅读:(132) ⋅ 点赞:(0)

在GROUP BY的使用过程中,SELECT 中出现的非组函数的字段必须声明在 GROUP BY 中。

还记得 MySQL零散拾遗(四) 中,提到的 GROUP BY 的使用要点嘛?

SELECT 中出现的非组函数的字段必须声明在 GROUP BY 中。反而,在 GROUP BY 中声明的字段可以不出现在SEELCT中。

现在就用个案例对其进行解释 o.O

GROUP BY 作用的只有分组列和聚合函数列,其他列不管用,返回的其他列只有对应的第一行

首先,我们来看一个具体的例子:

假设有一个 employees 表,包含以下数据:

employee_id last_name job_id salary
1 Smith CLERK 1000
2 Johnson CLERK 1200
3 Williams MANAGER 3000
4 Jones CLERK 1100
5 Brown CLERK 800

现在我们执行以下查询:

SELECT job_id, last_name, MAX(salary)
FROM employees
GROUP BY job_id;

结果如下:

job_id last_name MAX(salary)
CLERK Jones 1200
MANAGER Williams 3000

你可以观察到:

  1. GROUP BY 的作用对象是 job_id 列,也就是说查询结果会根据 job_id 进行分组。
  2. 在每个分组内,我们使用了聚合函数 MAX(salary) 来获取该分组内工资最高的值。
  3. 但对于 last_name 列,它并不是分组列也不是聚合函数,因此 SELECT 中返回的 last_name 值是该分组中第一条记录的 last_name

也就是说,GROUP BY 作用的是分组列和聚合函数列,其他列只能取该分组中的第一条记录的值。

再来看另一个例子:

SELECT job_id, last_name, salary 
FROM employees
GROUP BY job_id, last_name;

结果如下:

job_id last_name salary
CLERK Brown 800
CLERK Jones 1100
CLERK Johnson 1200
CLERK Smith 1000
MANAGER Williams 3000

这里我们在 GROUP BY 中同时指定了 job_idlast_name,因此查询结果中每一行对应一个独特的 job_idlast_name 组合,salary 也是该组合的实际值。

总之,GROUP BY 的作用是将查询结果按照指定的列进行分组,分组内使用聚合函数进行计算,而其他非分组列和非聚合函数列则返回该分组中的第一条记录的值。

额…想手动实现一下,但创建表太麻烦了,(⊙﹏⊙)
莫事儿莫事儿,我还找到了对应的 OJ 题,3,2,1,“上链接”
产品销售分析 III

这道题的要求:选出每个售出过的产品 第一年 销售的 产品 id年份数量价格

重点在于 第一年,这时候脑子里就出现一个想法(自行脑补那个表情包,哈哈哈哈)直接对product_id字段进行分组,然后使用 MIN(year) 不就行了嘛!

SELECT product_id, year first_year, quantity, price
FROM sales
GROUP BY product_id
HAVING year = MIN(year);

额,这种做法其实是错误的
对其进行改进改进就行了,使用子查询先把product_idyear进行筛选,再进行外层筛选

SELECT product_id, year first_year, quantity, price
FROM sales
WHERE (product_id, year) IN (
    SELECT product_id, MIN(year)
    FROM sales
    GROUP BY product_id
);

还可以使用开窗函数 rank

SELECT product_id, year first_year, quantity, price
FROM (SELECT *,
        RANK() OVER(PARTITION BY product_id ORDER BY year) as ranking
      FROM sales
) rank_table
WHERE ranking = 1

rank函数进行介绍一下

Rank 开窗函数是 SQL 中一种用于对查询结果集中的行进行 排名 的开窗函数。它可以根据指定的列或表达式对结果集中的行进行排序,并为每一行分配一个排名。在排名过程中,相同的值将被赋予相同的排名,而不同的值将被赋予不同的排名。

当存在并列(相同排序值)时,Rank 会跳过后续排名,并保留相同的排名。

Rank 开窗函数的常见用法是在查询结果中查找前几名(Top N)或排名最高的行。

Rank 开窗函数的语法如下:

RANK() OVER (
  PARTITION BY 列名1, 列名2, ... -- 可选,用于指定分组列
  ORDER BY 列名3 [ASC|DESC], 列名4 [ASC|DESC], ... -- 用于指定排序列及排序方式
) AS rank_column

其中,PARTITION BY 子句可选,用于指定分组列,将结果集按照指定列进行分组;ORDER BY 子句用于指定排序列及排序方式,决定了计算 Rank 时的排序规则。AS rank_column 用于指定生成的 Rank 排名列的别名。


网站公告

今日签到

点亮在社区的每一天
去签到