SQL进阶

1、CASE WHEN函数语句多条件

-- 请在此处输入 SQL
select name, 
case when (age>60) then '老同学'
     when (age>20) then '年轻' 
     else '小同学'
     end as age_level
from student
order by name

2、函数 - 时间函数

  • DATE:获取当前日期
  • DATETIME:获取当前日期时间
  • TIME:获取当前时间
-- 获取当前日期
SELECT DATE() AS date();

-- 获取当前时间
SELECT TIME() AS time();

-- 获取当前日期时间
SELECT DATETIME() AS datetime();

date()

time()datetime()
2023-08-0114:30:002023-08-01 14:30:00

3、函数 - 字符串处理

字符串进行各种操作,如转换大(upper)小(lower)写、计算字符串长度(length)以及搜索和替换子字符串等。

4、聚合函数:汇总计算

  • COUNT():计算指定列的行数或非空值的数量。
  • SUM():计算指定列的数值之和。
  • AVG():计算指定列的数值平均值。
  • MAX():找出指定列的最大值。
  • MIN():找出指定列的最小值。

5、分组聚合 - 多字段分组

要查询使用多字段分组查询表中 每个客户 购买的 每种商品 的总金额,相当于按照客户编号和商品编号分组:

-- 查询每个用户购买的每种商品的总金额,按照客户编号和商品编号分组
SELECT customer_id, product_id, SUM(amount) AS total_amount
FROM orders
GROUP BY customer_id, product_id;

6、关联查询

6.1 (cross)join或者 ,------笛卡尔积

方式1(,):
SELECT e.emp_name, e.salary, e.department, d.manager
FROM 
employees e,departments d;

方式2(join):
SELECT e.emp_name, e.salary, e.department, d.manager
FROM 
employees e JOIN departments d;

方式3(cross join):
SELECT e.emp_name, e.salary, e.department, d.manager
FROM 
employees e CROSS JOIN departments d;

员工表 employeesemp_id(员工编号)、emp_name(员工姓名)、department(所属部门)、salary(工资)。数据如下:

emp_idemp_namedepartmentsalary
1小明技术部5000
2鸡哥财务部6000
3李华销售部4500

部门表 departmentsdepartment(部门名称)、manager(部门经理)、location(所在地)。数据如下:

departmentmanagerlocation
技术部张三上海
财务部李四北京
销售部王五

广州

查询结果:

emp_namesalarydepartmentmanager
小明5000技术部张三
小明5000财务部李四
小明5000销售部王五
鸡哥6000技术部张三
鸡哥6000财务部李四
鸡哥6000销售部王五
李华4500技术部张三
李华4500财务部李四
李华4500销售部王五

6.2 (inner)join on

方式1
SELECT e.emp_name, e.salary, e.department, d.manager
FROM employees e
JOIN departments d ON e.department = d.department;

方式2
SELECT e.emp_name, e.salary, e.department, d.manager
FROM employees e
INNER JOIN departments d ON e.department = d.department;

员工表 employeesemp_id(员工编号)、emp_name(员工姓名)、department(所属部门)、salary(工资)。数据如下:

emp_idemp_namedepartmentsalary
1小明技术部5000
2鸡哥财务部6000
3李华销售部4500

部门表 departmentsdepartment(部门名称)、manager(部门经理)、location(所在地)。数据如下:

departmentmanagerlocation
技术部张三上海
财务部李四北京
销售部王五广州
摸鱼部赵二吐鲁番

查询结果如下:

emp_namesalarydepartmentmanager
小明5000技术部张三
鸡哥6000财务部李四
李华4500销售部王五

6.3 OUTER JOIN 中,包括 LEFT OUTER JOIN 和 RIGHT OUTER JOIN 

left join

员工表 employeesemp_id(员工编号)、emp_name(员工姓名)、department(所属部门)、salary(工资)。数据如下:

emp_idemp_namedepartmentsalary
1小明技术部5000
2鸡哥财务部6000
3李华销售部4500

部门表 departmentsdepartment(部门名称)、manager(部门经理)、location(所在地)。数据如下:

departmentmanagerlocation
技术部张三上海
财务部李四北京
人事部王五广州
摸鱼部赵二吐鲁番
SELECT e.emp_name, e.salary, e.department, d.manager
FROM 
employees e LEFT JOIN departments d 
ON e.department = d.department;

查询结果:

emp_namesalarydepartmentmanager
小明5000技术部张三
鸡哥6000财务部李四
李华4500销售部NULL

right join

员工表 employeesemp_id(员工编号)、emp_name(员工姓名)、department(所属部门)、salary(工资)。数据如下:

emp_idemp_namedepartmentsalary
1小明技术部5000
2鸡哥财务部6000
3李华销售部4500

部门表 departmentsdepartment(部门名称)、manager(部门经理)、location(所在地)。数据如下:

departmentmanagerlocation
技术部张三上海
财务部李四北京
人事部王五广州
摸鱼部赵二吐鲁番
SELECT e.emp_name, e.salary, e.department, d.manager
FROM 
employees e RIGHT JOIN departments d 
ON e.department = d.department;

查询结果:

7、查询进阶 - 组合查询:UNION 和 UNION ALL

table1 表:

emp_idnameagedepartment
101Alice25HR
102Bob28Finance
103Charlie22IT

table2 表:

emp_idnameagedepartment
101Alice25HR
201David27Finance
202Eve24HR
203Frank26IT

7.1 UNION 操作的结果,去除了重复的行(名称为 Alice):

SELECT name, age, department
FROM table1
UNION
SELECT name, age, department
FROM table2;
nameagedepartment
Alice25HR
Bob28Finance
Charlie22IT
David27Finance
Eve24HR
Frank26IT

7.2 UNION ALL 操作,保留了重复的行::

SELECT name, age, department
FROM table1
UNION
SELECT name, age, department
FROM table2;
nameagedepartment
Alice25HR
Bob28Finance
Charlie22IT
Alice25HR
David27Finance
Eve24HR
Frank26IT

8、开窗函数

开窗函数是一种强大的查询工具,它允许我们在查询中进行对分组数据进行计算、 同时保留原始行的详细信息 。

8.1 sum over(分组统计)

SUM(计算字段名) OVER (PARTITION BY 分组字段名)

订单表 orders,表格数据如下:

order_idcustomer_idorder_datetotal_amount
11012023-01-01200
21022023-01-05350
31012023-01-10120
41032023-01-15500

计算每个客户的订单总金额,并显示每个订单的详细信息。

SELECT 
    order_id, 
    customer_id, 
    order_date, 
    total_amount,
    SUM(total_amount) OVER (PARTITION BY customer_id) AS customer_total_amount
FROM
    orders;

查询结果:

order_idcustomer_idorder_datetotal_amountcustomer_total_amount
11012023-01-01200320
31012023-01-10120320
21022023-01-05350350
41032023-01-15500500

在上面的示例中,我们使用开窗函数 SUM 来计算每个客户的订单总金额(customer_total_amount),并使用 PARTITION BY 子句按照customer_id 进行分组。从前两行可以看到,开窗函数保留了原始订单的详细信息,同时计算了每个客户的订单总金额。

8.2 sum over order by(同组内数据的 累加求和 )

SUM(计算字段名) OVER (PARTITION BY 分组字段名 ORDER BY 排序字段 排序规则)

orders,表格数据如下:

order_idcustomer_idorder_datetotal_amount
11012023-01-01200
21022023-01-05350
31012023-01-10120
41032023-01-15500

计算每个客户的历史订单累计金额,并显示每个订单的详细信息。

SELECT 
    order_id, 
    customer_id, 
    order_date, 
    total_amount,
    SUM(total_amount) OVER (PARTITION BY customer_id ORDER BY order_date ASC) AS cumulative_total_amount
FROM
    orders;

结果将是:

order_idcustomer_idorder_datetotal_amountcumulative_total_amount
11012023-01-01200200
31012023-01-10120320
21022023-01-05350350
41032023-01-15500

500

在上面的示例中,我们使用开窗函数 SUM 来计算每个客户的历史订单累计金额(cumulative_total_amount),并使用 PARTITION BY 子句按照 customer_id 进行分组,并使用 ORDER BY 子句按照 order_date 进行排序。从结果的前两行可以看到,开窗函数保留了原始订单的详细信息,同时计算了每个客户的历史订单累计金额;相比于只用 sum over,同组内的累加列名称

8.3 rank(用于对查询结果集中的行进行 排名)

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

表 orders,表格数据如下:

order_idcustomer_idorder_datetotal_amount
11012023-01-01200
21022023-01-05350
31012023-01-10120
41032023-01-15500

为每个客户的订单按照订单金额降序排名,并显示每个订单的详细信息。

SELECT 
    order_id, 
    customer_id, 
    order_date, 
    total_amount,
    RANK() OVER (PARTITION BY customer_id ORDER BY total_amount DESC) AS customer_rank
FROM
    orders;

查询结果:

order_idcustomer_idorder_datetotal_amountcustomer_rank
11012023-01-012001
31012023-01-101202
21022023-01-053501
41032023-01-155001

在上面的示例中,我们使用开窗函数 RANK 来为每个客户的订单按照订单金额降序排名(customer_rank),并使用 PARTITION BY 子句按照 customer_id 进行分组,并使用 ORDER BY 子句按照 total_amount 从大到小进行排序。

可以看到,开窗函数保留了原始订单的详细信息,同时计算了每个客户的订单金额排名。

8.4 row_number(为查询结果集中的每一行 分配唯一连续排名)

表 orders,表格数据如下:

order_idcustomer_idorder_datetotal_amount
11012023-01-01200
21022023-01-05350
31012023-01-10120
41032023-01-15

500

为每个客户的订单按照订单金额降序排列,并且分配一个 row_number 编号。

SELECT 
    order_id, 
    customer_id, 
    order_date, 
    total_amount,
    ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY total_amount DESC) AS row_number
FROM
    orders;

结果将是:

order_idcustomer_idorder_datetotal_amountrow_number
41032023-01-155001
21022023-01-053501
11012023-01-012001
31012023-01-10120

2

在上面的示例中,我们使用开窗函数 ROW_NUMBER 为每个客户的订单按照订单金额降序排列,并为每个订单分配了一个编号(row_number),并使用 PARTITION BY 子句按照 customer_id 进行分组,并使用 ORDER BY 子句按照 total_amount 进行排序。

8.5 lag/lead(获取在当前行之前或之后的行的值)

💡 比较相邻行数据或进行时间序列分析时非常有用

LAG(取值的列名, 向⬆️偏移的行数, 指定当没有前一行时的默认值) OVER (PARTITION BY 分组字段名 ORDER BY 排序字段名)

LEAD(取值的列名, 向⬇️偏移的行数, 指定当没有前一行时的默认值) OVER (PARTITION BY 分组字段名 ORDER BY 排序字段名)

学生成绩表scores,其中包含学生的成绩和考试日期:

student_idexam_datescore
1012023-01-0185
1012023-01-0578
1012023-01-1092
1012023-01-15

80

查询每个学生的考试日期和上一次考试的成绩,以及下一次考试的成绩。

SELECT 
    student_id,
    exam_date,
    score,
    LAG(score, 1, NULL) OVER (PARTITION BY student_id ORDER BY exam_date) AS previous_score,
    LEAD(score, 1, NULL) OVER (PARTITION BY student_id ORDER BY exam_date) AS next_score
FROM
    scores;

结果将是:

student_idexam_datescoreprevious_scorenext_score
1012023-01-0185NULL78
1012023-01-05788592
1012023-01-10927880
1012023-01-158092NULL

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值