力扣刷题(sql)--零散知识点(1)

news2024/11/24 22:24:12

通过一段时间的刷题,感觉自己的sql能力逐渐上去,所以不会像前三道题一样讲那么详细了,这里主要会讲到一些特殊的知识点和方法。另外,我的建议是做完一个题有好的想法赶紧记录下来,不要想着最后汇总,不然会懒得整理,也会忘记一些当时才发现的知识点。

------------------------------------------------------------------------------------------------------------------------

1. 不用if的sum

这里的sum(order_date= customer_pref_delivery_date),没有用到if也能用聚集函数sum把满足order_date= customer_pref_delivery_date条件的行数加起来。说明有的时候可以不用if,用if的话还要设置两个正确与否的值,通常是1和0.

select
    round(sum(order_date= customer_pref_delivery_date)/count(*)*100,2) immediate_percentage
from
    delivery
where
    (customer_id,order_date)
in
    (select
        customer_id, min(order_date)  
    from
        delivery
    group by
        customer_id);

2. 多个列名的in

上面代码的where后面是判断某一行中两列对应的值能否另一个表(这里是个子查询)对上。我们之前往往用到的都是只有一个列,比如where id in (201,203),这里可以很好的扩展思维,个人认为很有用的知识点。

3. datediff的误区

select
    activity_date day , count(distinct user_id) active_users
from
    activity
where
    datediff('2019-07-27',activity_date)<29
group by
    activity_date;

这里我想找出activity_date在’2019-07-27’近 30 天的日期,但是后面我发现这是错的,因为没有限制 activity_date 不能超出‘2019-07-27’。这会导致某些未来的日期(如 2019-08-252021-08-25)也符合条件(做差后为负数,也小于29)。

所以解决这一问题的方法就是用between。between也有两种用法:

activity_date BETWEEN DATE_SUB('2019-07-27', INTERVAL 29 DAY) AND '2019-07-27'

DATEDIFF('2019-07-27', activity_date) BETWEEN 1 AND 29

以上两种都可以实现找到近 30 天日期的作用。

******值得一提的是,题目要求近30天,而上面的代码输入的关键字都是29,这点需要注意,因为DATEDIFF() 的结果是天数差,不包括起始日期的那一天。

4. min()求最小日期

MIN()函数:会返回某个列中的最小值,在时间数据上,它返回最早的日期。

select MIN(activity_date) from activity;

5. lag()窗口函数

刷题的时候用到了一下,感觉特别好用,再次讲解一下,这次还用到了“PARTITION BY

LAG() 是 SQL 中的一种窗口函数,用于获取当前行的前一行的值,而无需在查询中自连接。这在需要对比相邻记录(如日期、订单、活动等)时非常有用。 

语法如下:

LAG(column_name, [offset], [default_value]) 
OVER (PARTITION BY partition_column ORDER BY order_column)

实际用例:

user_idactivity_dateactivity_type
12019-07-20open_session
12019-07-21send_message
12019-07-22end_session
22019-07-21open_session
22019-07-23end_session
SELECT 
    user_id, 
    activity_date, 
    activity_type,
    LAG(activity_date) OVER (PARTITION BY user_id ORDER BY activity_date) AS previous_activity_date
FROM 
    activity;

结果:

user_idactivity_dateactivity_typeprevious_activity_date
12019-07-20open_sessionNULL
12019-07-21send_message2019-07-20
12019-07-22end_session2019-07-21
22019-07-21open_sessionNULL
22019-07-23end_session2019-07-21

有的时候还是能发挥一定的作用。 

6.筛选部分组内数据满足条件的分组

例题:编写解决方案,报告 2019年春季 才售出的产品。即 仅 在 2019-01-01 (含)至 2019-03-31 (含)之间出售的商品。

输入:
Product table:
+------------+--------------+------------+
| product_id | product_name | unit_price |
+------------+--------------+------------+
| 1          | S8           | 1000       |
| 2          | G4           | 800        |
| 3          | iPhone       | 1400       |
+------------+--------------+------------+
table:
+-----------+------------+----------+------------+----------+-------+
| seller_id | product_id | buyer_id | sale_date  | quantity | price |
+-----------+------------+----------+------------+----------+-------+
| 1         | 1          | 1        | 2019-01-21 | 2        | 2000  |
| 1         | 2          | 2        | 2019-02-17 | 1        | 800   |
| 2         | 2          | 3        | 2019-06-02 | 1        | 800   |
| 3         | 3          | 4        | 2019-05-13 | 2        | 2800  |
+-----------+------------+----------+------------+----------+-------+
输出:
+-------------+--------------+
| product_id  | product_name |
+-------------+--------------+
| 1           | S8           |
+-------------+--------------+

 刚开始我写的代码如下:

select
    p.product_id, p.product_name
from
    product p
join
    sales s
on
    p.product_id = s.product_id
and
    date(s.sale_date) between '2019-01-01' and '2019-03-31'; 

上面代码利用简单联结找出sale_date在2019-01-01到2019-03-31,这样会返回错误的结果,因为产品2不仅在这个区间里出售了,在其他区间也出售了,没有实现“仅”的目的。

后面使用分组(group by+having)的办法,比较巧妙的解决了这一问题,即对该组内所有数据都进行验证,排除这种有的满足、有的不满足的数据,却加入了要求所有数据满足的分组里面。

# Write your MySQL query statement below
select
    p.product_id, p.product_name
from
    product p
join
    sales s
on
    p.product_id = s.product_id
group by
    p.product_id, p.product_name
having
    min(sale_date) >= '2019-01-01' and max(sale_date) <= '2019-03-31';

即GROUP BY + HAVING:适用于简单的按组汇总,并进行唯一性判断。

7. distinct在多列上的的使用

DISTINCT 是 SQL 中的关键字,用于去除查询结果中的重复行,返回唯一值。它通常用于 SELECT 语句中,确保查询的结果集中不包含重复的数据。

这里DISTINCT 不仅可以应用于单列,也可以用于多个列(放在多个列名的最前面),它会返回这些列的组合的唯一值。

SELECT DISTINCT product_id FROM sales;

SELECT DISTINCT product_id, buyer_id FROM sales;

---------------------------------------------------------------------------------------------------------------------------------例题: 一个员工可以属于多个部门。当一个员工加入超过一个部门的时候,他需要决定哪个部门是他的直属部门。请注意,当员工只加入一个部门的时候,那这个部门将默认为他的直属部门,虽然表记录的值为'N'.

输入:
Employee table:
+-------------+---------------+--------------+
| employee_id | department_id | primary_flag |
+-------------+---------------+--------------+
| 1           | 1             | N            |
| 2           | 1             | Y            |
| 2           | 2             | N            |
| 3           | 3             | N            |
| 4           | 2             | N            |
| 4           | 3             | Y            |
| 4           | 4             | N            |
+-------------+---------------+--------------+
输出:
+-------------+---------------+
| employee_id | department_id |
+-------------+---------------+
| 1           | 1             |
| 2           | 1             |
| 3           | 3             |
| 4           | 3             |
+-------------+---------------+

这题我写了很长串,思路是先把有“Y”的分一组,然后其他没“Y”就是只有一行的分一组,然后拼起来。我觉得太长,而gpt给出了两种方法,可以来学习一下。(gpt懂得太多了,有能借鉴而且实用的才拿出来记录下。)

8. max()配合case求出分组中某个符合条件的值

如图所示,下面是上一题的更优解,这里用到了一些配合。

SELECT 
    employee_id, 
    COALESCE(
        MAX(CASE WHEN primary_flag = 'Y' THEN department_id ELSE NULL END),
        MAX(department_id)
    ) AS department_id
FROM 
    employee
GROUP BY 
    employee_id;

首先来个错误示范(我写的):

SELECT 
    employee_id, 
    if(primary_flag='Y',department_id,null) department_id
FROM 
    employee
GROUP BY 
    employee_id;

代码意思好像要求把分组后primary_flag='Y'的department_id值打印出来,结果如图:

employee_id为1和3返回null正常,它们没有符合primary_flag='Y'条件的行,但employee_id为4有满足条件的行,但也返回null,说明语法还是有问题,貌似这里只会判断每一组的第一行是否满足rimary_flag='Y'条件,所有2有返回值,4返回null

这里就要配合max()函数了,MAX(CASE WHEN primary_flag = 'Y' THEN department_id ELSE NULL END),这里if和case差别不大,作用都一样,条件语句把每一组的每一行判断条件后每一行都会得到要么是一个数值,要么是null,用max()比较数值和null后,就能让那个合适的返回值返回出来了。

这里加上max()函数后,2和4就能正常返回正确的department_id值了,但1和3依旧返回null,因为它们压根没有primary_flag='Y'条件的行啊。为了满足题意,即只有一行时,不管primary_flag='Y'条件是否成立,都返回其department_id,那还要配合COALESCE()。 

9.COALESCE()

COALESCE() 是 SQL 中的一个非常实用的空值处理函数,用于返回第一个非 NULL 的值。它的主要作用是提供一个默认值,避免返回 NULL 结果。这个函数在处理缺失数据、替代空值、进行多层判断时非常有用。coalesce(合并的意思)

COALESCE(value1, value2, ..., valueN)

下面的代码当employee_id的1、3的max()配合case依然返回null后,直接返回其department_id,这个不是null,直接返回。

 COALESCE(
        MAX(CASE WHEN primary_flag = 'Y' THEN department_id ELSE NULL END),
        department_id
    )

8、9的总结:希望能很好地帮助到以后对某个列分组后求另外一个列符合条件的值。 

10. ROW_NUMBER()

依然是刚才那题,看一下另一种思路:

WITH ranked_departments AS (
    SELECT 
        employee_id, 
        department_id, 
        ROW_NUMBER() OVER (
            PARTITION BY employee_id 
            ORDER BY primary_flag DESC
        ) AS rn
    FROM 
        employee
)
SELECT 
    employee_id, 
    department_id
FROM 
    ranked_departments
WHERE 
    rn = 1;

这些代码的思路大概是:用到了一个类似子表的东西,同时自己设置了一列,这一列是利用ROW_NUMBER(),根据employee_id分区,然后通过primary_flag这一列来排序最终设计得到,最后在新表中根据新得到的这一列,取出新列中所有编号为1的employee_id, department_id.

这里的语法和之前的lag()函数一样。

ROW_NUMBER() 是 SQL 中的一个窗口函数,用于为查询结果中的每一行分配一个唯一的编号,这个编号通常按某种顺序排列(如时间、ID等)。它常用于需要按某种顺序进行排序、排名或者找出每个分组的第一条或最后一条记录的场景。

ROW_NUMBER() OVER (PARTITION BY partition_column ORDER BY order_column)

这种编号后提取指定编号的思维值得学习。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2224674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STATCOM静止同步补偿器原理及MATLAB仿真模型

STATCOM原理简述 整个STATCOM 装置相当于一个电压大小可以控制的电压源。当控制 STATCOM 装置产生的电压小于系统电压即UI<US 时&#xff0c;STATCOM 装置向系统输出的无功功率Q<0&#xff0c;此时 STATCOM 装置相当于电感&#xff1b;当控制 STATCOM 装置产生的电压大于…

编写一个简单的Iinput_dev框架

往期内容 本专栏往期内容&#xff1a; input子系统的框架和重要数据结构详解-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客 I2C子系统专栏&#xff1a; 专栏地址&#xff1a;IIC子系统_憧憬…

理工科考研想考计算机,湖南大学、重大、哈工大威海、山东大学,该如何选择?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 计算机对理工科同学来说&#xff0c;还是性价比很高的&#xff0c;具有很大的优势&#xff01; 一、就业前景广阔 高需求行业 在当今数字化时代&#xff0c;计算机技术几乎渗透到了各个领域&#xff0c;无论是互联网…

在MacOS玩RPG游戏 - RPGViewerPlus

背景知识 由于我一直使用Mac电脑&#xff0c;所以一直对Mac如何玩RPGMV/RPGMZ游戏的方式有进一步的想法。 网上能给出的方案都是自行启动一个HTTP服务进行&#xff0c;进行服务加载。这个方法有效&#xff0c;但兼容性较差。涉及到自定义功能模块的游戏&#xff0c;都会有报错…

十分钟Linux中的epoll机制

epoll机制 epoll是Linux内核提供的一种高效I/O事件通知机制&#xff0c;用于处理大量文件描述符的I/O操作。它适合高并发场景&#xff0c;如网络服务器、实时数据处理等&#xff0c;是select和poll的高效替代方案。 1. epoll的工作原理 epoll通过内核中的事件通知接口和文件…

FlinkSQL之temporary join开发

在实时开发中&#xff0c;双流join获取目标对应时刻的属性时&#xff0c;经常使用temporary join。笔者在流量升级的实时迭代中&#xff0c;需要让流量日志精准的匹配上浏览时间里对应的商品属性&#xff0c;使用temporary join开发过程中踩坑不少&#xff0c;将一些经验沉淀在…

Flutter鸿蒙next 中如何实现 WebView【跳、显、适、反】等一些基础问题

✅近期推荐&#xff1a;求职神器 https://bbs.csdn.net/topics/619384540 &#x1f525;欢迎大家订阅系列专栏&#xff1a;flutter_鸿蒙next &#x1f4ac;淼学派语录&#xff1a;只有不断的否认自己和肯定自己&#xff0c;才能走出弯曲不平的泥泞路&#xff0c;因为平坦的大路…

使用C#学习Office文件的处理(pptx docx xlsx)

Office文件 是指PPT 、word、Excel 这些常用工具生成的文件 &#xff0c;例如 pptx docx xlsx。 这些文件的读取和生成有很多很多库 例如 NOPI 、DevExpress、C1、Aspose、Teleric 等等&#xff0c;各有各的优缺点。俺今天不讲这个&#xff0c;俺只是讲讲如何了解Office文件的…

css实现外层不换行,内层换行

css实现上图效果&#xff0c;内容A和B整体不换行&#xff0c;B内容中换行 <div className"description"> <div className"label">{formatMessage({id: description})}</Col> <divclassName"value"> &l…

Pr 视频效果:波形变形

视频效果/扭曲/波形变形 Distort/Wave Warp 波形变形 Wave Warp效果用于在剪辑上创建类似波浪的动态变形效果。 此效果会自动动画化&#xff0c;波形以恒定速度移动。要改变速度或停止波动&#xff0c;需要设置关键帧。 ◆ ◆ ◆ 效果选项说明 通过调整波形的类型、高度、宽度…

一分钟看懂死锁的概念

&#x1f449; 请点赞支持这款 全新设计的脚手架 &#xff0c;让 Java 再次伟大&#xff01; 什么是死锁 当线程 A 持有独占锁 a&#xff0c;并尝试去获取独占锁 b 的同时&#xff0c;线程 B 持有独占锁 b &#xff0c;并尝试获取独占锁 a 的情况下&#xff0c;就会发生 AB 两…

挂耳式耳机品牌排行榜前十名有哪些?平价开放式耳机品牌推荐!

可能我们经常能够看到不少小伙伴佩戴普通蓝牙耳机跑步健身&#xff0c;确实让人羡慕&#xff0c;但我始终觉得入耳式耳机并不适合长时间的运动佩戴。就以我个人为例&#xff0c;由于耳孔较大&#xff0c;普通入耳式耳机在运动中很难稳固地佩戴&#xff0c;经常发生耳机掉落甚至…

SMA-BP时序预测 | Matlab实现SMA-BP黏菌算法优化BP神经网络时间序列预测

SMA-BP时序预测 | Matlab实现SMA-BP黏菌算法优化BP神经网络时间序列预测 目录 SMA-BP时序预测 | Matlab实现SMA-BP黏菌算法优化BP神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现SMA-BP黏菌算法优化BP神经网络时间序列预测&#xff08;完…

[论文笔记]ColPali: Efficient Document Retrieval with Vision Language Models

引言 今天带来一篇多模态RAG的论文笔记&#xff1a;ColPali: Efficient Document Retrieval with Vision Language Models。 引入了一种利用视觉语言模型文档理解能力的检索模型架构ColPali&#xff0c;从文档页面图像上生成高质量的上下文嵌入&#xff0c;结合延迟交互匹配机…

算法刷题基础知识总结

文章目录 处理输入输出常用数据结构数学知识数论基础质数和合数因数/约数互为质数 阶乘排列与组合 排序字典序Comparator接口 处理输入输出 Scanner 类可以读取多种类型的数据&#xff0c;包括&#xff1a; nextInt()&#xff1a;读取整数。nextDouble()&#xff1a;读取双精…

vitepress一键push和发布到github部署网站脚本

文章目录 前言一、viteress基本结构二、脚本1、push2、dev 总结 前言 没啥可说的 脚本是bat文件&#xff0c;直接双击运行 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、viteress基本结构 创建完你的文档&#xff0c;目录如下 ---bin ---docs …

java计算机毕设课设—写字板程序(附源码、文章、相关截图、部署视频)

这是什么系统&#xff1f; 资源获取方式再最下方 java计算机毕设课设—写字板程序(附源码、文章、相关截图、部署视频) 一、项目简介 本毕设旨在开发一个高效、易用的基于Java的写字板程序&#xff0c;通过利用Java的Swing库构建用户界面&#xff0c;实现基本的文本编辑功能…

Ubuntu 22.04系统启动时自动运行ROS2节点

在 Ubuntu 启动时自动运行 ROS2 节点的方法 环境&#xff1a;Ubuntu 系统&#xff0c;ROS2 Humble&#xff0c;使用系统自带的 启动应用程序 目标&#xff1a;在系统启动时自动运行指定的 ROS2 节点 效果展示 系统启动后&#xff0c;自动运行小乌龟节点和键盘控制节点。 实践…

直接删除Github上的文件

直接删除Github上的文件 说明&#xff1a;此操作只删除Github上的文件&#xff0c;本地仓库文件不受影响 1.确定要删除哪个分支文件,以删除main为例&#xff0c; 1.找到本地仓库位置以StudyNote为例&#xff0c;右键 bash here 2.打开命令窗口&#xff0c;将Github的StudyN…

个体能量的勇气层级是否容易达到?

没有勇气面对现实&#xff0c;没有勇气改变自我&#xff0c;没有勇气改变环境&#xff0c;没有勇气创新创造。 这是常态。 如何找寻高质量免费机器人工程资源自学提升-CSDN博客 个人能力的提升&#xff0c;也包括个体能量的提升。 个体能量是个人能力的一个非常重要的衡量指…