在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 | 
你可以观察到:
- GROUP BY的作用对象是- job_id列,也就是说查询结果会根据- job_id进行分组。
- 在每个分组内,我们使用了聚合函数 MAX(salary)来获取该分组内工资最高的值。
- 但对于 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_id 和 last_name,因此查询结果中每一行对应一个独特的 job_id 和 last_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_id和year进行筛选,再进行外层筛选
SELECT product_id, year first_year, quantity, price
FROM sales
WHERE (product_id, year) IN (SELECT product_id, MIN(year)FROM salesGROUP BY product_id
);
还可以使用开窗函数 rank
SELECT product_id, year first_year, quantity, price
FROM (SELECT *,RANK() OVER(PARTITION BY product_id ORDER BY year) as rankingFROM 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 排名列的别名。