当前位置: 首页 > article >正文

SQL-leetcode—1179. 重新格式化部门表

1179. 重新格式化部门表

表 Department:

±--------------±--------+
| Column Name | Type |
±--------------±--------+
| id | int |
| revenue | int |
| month | varchar |
±--------------±--------+
在 SQL 中,(id, month) 是表的联合主键。
这个表格有关于每个部门每月收入的信息。
月份(month)可以取下列值 [“Jan”,“Feb”,“Mar”,“Apr”,“May”,“Jun”,“Jul”,“Aug”,“Sep”,“Oct”,“Nov”,“Dec”]。

重新格式化表格,使得 每个月 都有一个部门 id 列和一个收入列。

以 任意顺序 返回结果表。

结果格式如以下示例所示。

示例 1:

输入:
Department table:
±-----±--------±------+
| id | revenue | month |
±-----±--------±------+
| 1 | 8000 | Jan |
| 2 | 9000 | Jan |
| 3 | 10000 | Feb |
| 1 | 7000 | Feb |
| 1 | 6000 | Mar |
±-----±--------±------+
输出:
±-----±------------±------------±------------±----±------------+
| id | Jan_Revenue | Feb_Revenue | Mar_Revenue | … | Dec_Revenue |
±-----±------------±------------±------------±----±------------+
| 1 | 8000 | 7000 | 6000 | … | null |
| 2 | 9000 | null | null | … | null |
| 3 | null | 10000 | null | … | null |
±-----±------------±------------±------------±----±------------+
解释:四月到十二月的收入为空。
请注意,结果表共有 13 列(1 列用于部门 ID,其余 12 列用于各个月份)。

题解

格式化表格,使得 每个月 都有一个部门 id 列和一个收入列

  • 经典的行转列,可以使用聚合函数+group by + case when来实现

方法一 SUM + group by

select
    id
    ,SUM(case when month='Jan' then revenue else null end) as Jan_Revenue
    ,SUM(case when month='Feb' then revenue else null end) as Feb_Revenue
    ,SUM(case when month='Mar' then revenue else null end) as Mar_Revenue
    ,SUM(case when month='Apr' then revenue else null end) as Apr_Revenue
    ,SUM(case when month='May' then revenue else null end) as May_Revenue
    ,SUM(case when month='Jun' then revenue else null end) as Jun_Revenue
    ,SUM(case when month='Jul' then revenue else null end) as Jul_Revenue
    ,SUM(case when month='Aug' then revenue else null end) as Aug_Revenue
    ,SUM(case when month='Sep' then revenue else null end) as Sep_Revenue
    ,SUM(case when month='Oct' then revenue else null end) as Oct_Revenue
    ,SUM(case when month='Nov' then revenue else null end) as Nov_Revenue
    ,SUM(case when month='Dec' then revenue else null end) as Dec_Revenue
from Department
group by id

方法二 MAX + group by

select
    id
    ,MAX(case when month='Jan' then revenue else null end) as Jan_Revenue
    ,MAX(case when month='Feb' then revenue else null end) as Feb_Revenue
    ,MAX(case when month='Mar' then revenue else null end) as Mar_Revenue
    ,MAX(case when month='Apr' then revenue else null end) as Apr_Revenue
    ,MAX(case when month='May' then revenue else null end) as May_Revenue
    ,MAX(case when month='Jun' then revenue else null end) as Jun_Revenue
    ,MAX(case when month='Jul' then revenue else null end) as Jul_Revenue
    ,MAX(case when month='Aug' then revenue else null end) as Aug_Revenue
    ,MAX(case when month='Sep' then revenue else null end) as Sep_Revenue
    ,MAX(case when month='Oct' then revenue else null end) as Oct_Revenue
    ,MAX(case when month='Nov' then revenue else null end) as Nov_Revenue
    ,MAX(case when month='Dec' then revenue else null end) as Dec_Revenue
from Department
group by id

方法三 MIN + group by

select
    id
    ,MIN(case when month='Jan' then revenue else null end) as Jan_Revenue
    ,MIN(case when month='Feb' then revenue else null end) as Feb_Revenue
    ,MIN(case when month='Mar' then revenue else null end) as Mar_Revenue
    ,MIN(case when month='Apr' then revenue else null end) as Apr_Revenue
    ,MIN(case when month='May' then revenue else null end) as May_Revenue
    ,MIN(case when month='Jun' then revenue else null end) as Jun_Revenue
    ,MIN(case when month='Jul' then revenue else null end) as Jul_Revenue
    ,MIN(case when month='Aug' then revenue else null end) as Aug_Revenue
    ,MIN(case when month='Sep' then revenue else null end) as Sep_Revenue
    ,MIN(case when month='Oct' then revenue else null end) as Oct_Revenue
    ,MIN(case when month='Nov' then revenue else null end) as Nov_Revenue
    ,MIN(case when month='Dec' then revenue else null end) as Dec_Revenue
from Department
group by id

可能一开始看到SUM、MAX、MIN会不理解为啥?

在这里插入图片描述
在这里插入图片描述

可以看下这2个图例呢?

中间分组的过程其实是内部存储的,无法查询出来的一个虚拟的结果,一个框是一个集合的内容,这样的话就比较好理解为啥用聚合函数了。

如果不使用聚合函数会怎么样呢?
如果不使用的话,行数不会减少,会和输入数据一样的行数,就需要考虑一个合并的问题了。
大致效果是:
1, 100,null,null,null,…
2,null,100,null,null,…
1,null,100,null,null,…

显然id=1的数据没有合并,违背了行转列的预期效果。

分析案例

解题思路
由于筛选结果中每个ID是一个记录 因此GROUP BY ID.
每个月份是一列,因此筛选每个月份时使用CASE [when…then…] END只取当前月份.
需要使用SUM()聚合函数 因为如果没有聚合函数 筛选出来的是
GROUP BY、CASE…END之后的第一行.

比如 Department 表:
+------+---------+-------+
| id   | revenue | month |
+------+---------+-------+
| 1    | 8000    | Jan   |
| 2    | 9000    | Jan   |
| 3    | 10000   | Feb   |
| 1    | 7000    | Feb   |
| 1    | 6000    | Mar   |
+------+---------+-------+

GROUP BY ID
+------+---------+-------+
| id   | revenue | month |
+------+---------+-------+
| 1    | 8000    | Jan   |
| 1    | 7000    | Feb   |
| 1    | 6000    | Mar   |
-------------------------
| 2    | 9000    | Jan   |
-------------------------
| 3    | 10000   | Feb   |
+------+---------+-------+


如果没有聚合函数 只输出第一行 比如
SELECT ID, (CASE WHEN MONTH='JAN' THEN REVENUE END) AS JAN_REVENUE, 
(CASE WHEN MONTH='FEB' THEN REVENUE END) AS FEB_REVENUE  
FROM DEPARTMENT GROUP BY ID
会输出
+------+-------------+-------------+
| ID   | JAN_REVENUE | FEB_REVENUE |
+------+-------------+-------------+
| 1    | 8000        | NULL        |
| 2    | 7000        | NULL        |
| 3    | NULL        | 10000       |
+------+-------------+-------------+
其中 ID=1 的 FEB_REVENUE 结果不对,这是因为 ID=1 时, (CASE WHEN MONTH='FEB' THEN REVENUE END)= [NULL, 7000, NULL], 没有聚合函数会只取第一个,即NULL

http://www.kler.cn/a/516895.html

相关文章:

  • Spring中的事务管理器TransactionManager
  • 【数据库】详解MySQL数据库中的事务与锁
  • 计算机网络之物理层
  • SpringBoot使用MockMVC通过http请求controller控制器调用测试
  • Vue中设置报错页面和“Uncaught runtime errors”弹窗关闭
  • docker ubuntu:20.04构建c++ grpc环境
  • Kingbase数据库体系结构和日常运维监控
  • Windows安装Miniconda和PySide6以及配置PyCharm
  • 0基础跟德姆(dom)一起学AI 自然语言处理21-fasttext模型架构
  • OpenVela 架构剖析:从内核到应用
  • 阿里云-银行核心系统转型之业务建模与技术建模
  • 大数据学习(38)- Flink运行时架构
  • ChatGPT大模型极简应用开发-CH4-GPT-4 和 ChatGPT 的高级技巧
  • SQL记录学习日志
  • 我谈《概率论与数理统计》的知识体系
  • python flask中使用or查询和and查询,还有同时使用or、and的情况
  • Vue实现div滚动,并且支持top动态滚动
  • windows修改host上github
  • 考研408笔记之数据结构(五)——图
  • 第04章 02 VTK管道的执行过程与类型
  • 2.7 createCmd中的visitor访问者设计模式
  • 基于微信小程序的设备故障报修管理系统设计与实现(LW+源码+讲解)
  • stm8s单片机(四)时钟输出与蜂鸣器实验
  • 【飞牛云访问本地NAS数据】手机飞牛云APP异地远程连接fnOS随时随地访问私有应用不受网络限制
  • vim如何设置制表符表示的空格数量
  • DRG/DIP 2.0时代下基于PostgreSQL的成本管理实践与探索(上)