数据库复杂查询

51 阅读3分钟

数据库复杂查询

基础

增删改查

进阶

聚合函数与分组查询

groud by分组

count(*)计数,以前面的为准,能够

以下方查询语句为例,查询count(*)实际上就是查找前面这个部门重复的人数,然后在通过分组返回数据

SELECT dept_id, COUNT(*) AS user_count
FROM users
GROUP BY dept_id;

那为什么要用groud by呢?

GROUP BY 决定“按哪个字段分组”,否则 SQL 不知道你要统计哪个部门。

那等于说用这个ground by进行分组,他会将你设置的字段将其合并在一起吗,比如我查找,部门名称,人数,性别,学号,然后用ground by 部门会是啥样的?

idnamedept_namegenderstudent_no
1张三数学1001
2李四数学1002
3王五语文1003
4赵六数学1004
SELECT dept_name, gender, COUNT(*) AS num_students
FROM students
GROUP BY dept_name;

会发生的错误,首先是count计算部门的数量之后,因为gender不是聚合函数,而且在group by里面也没有这个东西,所以会出现直接报错

但是如果

SELECT dept_name, gender, COUNT(*) AS num_students
FROM students
GROUP BY dept_name, gender;

这样的话就会按照dept——name以及gender进行排序

having(分组后的聚合函数需要用having而不是where)

WHERE 用于 行过滤(表中每一行)

HAVING 用于 分组过滤(GROUP BY 后的结果)

执行顺序(重要)
SELECT dept_name, COUNT(*) AS num_students
FROM students
GROUP BY dept_name
HAVING COUNT(*) > 2;

执行顺序:

  1. FROM students → 先拿到表的所有行

  2. GROUP BY dept_name → 按部门分组

    • 数学组:张三、李四
    • 语文组:王五
  3. COUNT(*) → 计算每组行数

    • 数学=2,语文=1
  4. HAVING COUNT(*) > 2 → 过滤

    • 数学=2 → 不满足 >2 → 被过滤
    • 语文=1 → 不满足 → 被过滤
  5. 最终返回空(如果没有部门人数 >2)

子查询

“查询比自己所在部门平均工资高的员工”

先分别查出来部门的平均工资,然后比较员工工资和部门平均工资

先查找每个员工所在部门的平均工资,select avg(sale)from 表 where 部门id=员工id

排序与分页

SELECT * FROM employees ORDER BY salary DESC desc就是降序,不加就是升序 LIMIT 0, 10; -- 第 1 页 LIMIT 10, 10; -- 第 2 页

复杂条件查询

窗口函数

查询每个部门工资排名前 3 的员工

select 员工 from 表 where 部门id=员工id order by 工资,limit 3

查询最新的数据使用的窗口函数

查询最新的数据ROW_NUMBER()RANK()

通常可以使用 ROW_NUMBER() 窗口函数,它会为每个分组内的行按指定顺序排定一个唯一的排名,最新的数据会被标记为排名 1。

SELECT a.name, b.policy_name, b.purchase_date,
       ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY b.purchase_date DESC) AS rank
FROM customers a
JOIN policies b ON a.id = b.customer_id
WHERE rank = 1;
​

查询最近七天的数据CURRENT_DATEDATE_SUB

虽然窗口函数本身并不能直接提供基于日期范围的筛选,但你可以在查询中使用 日期函数(如 CURRENT_DATE)来限制数据范围,再结合窗口函数来分析。

SELECT a.name, b.policy_name, b.purchase_date,
       ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY b.purchase_date DESC) AS rank
FROM customers a
JOIN policies b ON a.id = b.customer_id
WHERE b.purchase_date >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY);
​