做题笔记:SQL Sever 方式做牛客SQL的题目--VQ

----VQ 查询用户刷题日期和下一次刷题日期

现有牛客刷题记录表questions_pass_record ,请查询用户user_id,刷题日期date (每组按照date降序排列)和该用户的下一次刷题日期nextdate(若是没有则为None),组之间按照user_id升序排序,每组内按照date升序排列,查询返回结果名称和顺序为:

user_id|date|nextdate

表的创建及数据的添加:

sql 复制代码
drop table if exists questions_pass_record;
CREATE TABLE questions_pass_record
(
    user_id       int         NOT NULL,
    question_type varchar(32) NOT NULL,
    device        varchar(14) NOT NULL,
    question_id   int         NOT NULL,
    date          date        NOT NULL
);
INSERT INTO questions_pass_record
VALUES (101, 'java', 'app', 2, '2020-03-01');
INSERT INTO questions_pass_record
VALUES (102, 'sql', 'pc', 15, '2021-07-07');
INSERT INTO questions_pass_record
VALUES (102, 'python', 'pc', 9, '2021-04-09');
INSERT INTO questions_pass_record
VALUES (102, 'python', 'app', 3, '2022-03-17');
INSERT INTO questions_pass_record
VALUES (103, 'sql', 'pc', 60, '2018-08-15');
INSERT INTO questions_pass_record
VALUES (104, 'sql', 'pc', 20, '2019-05-15');
INSERT INTO questions_pass_record
VALUES (105, 'sql', 'pc', 550, '2022-07-25');
INSERT INTO questions_pass_record
VALUES (105, 'sql', 'pc', 299, '2020-05-16');
INSERT INTO questions_pass_record
VALUES (106, 'java', 'pc', 17, '2021-04-15');
INSERT INTO questions_pass_record
VALUES (106, 'java', 'pc', 20, '2021-04-15');

查询如下:

sql 复制代码
select q1.user_id, q1.date, q2.date as nextdate
 from (
		select  user_id, date, 
				row_number() over (partition by user_id order by date) as nextNum
        from questions_pass_record) q1
    left join
	  (
	    select  user_id, date, 
				row_number() over (partition by user_id order by date) as nextNum
        from questions_pass_record) q2
 on q1.user_id = q2.user_id and q1.nextNum + 1 = q2.nextNum

或者直接使用函数:

sql 复制代码
select user_id,date,
       lead(date, 1) over (partition by user_id order by date) as nextdate
from questions_pass_record

两个查询的执行结果都如下:

sql 复制代码
user_id	date		nextdate
101		2020-03-01	NULL
102		2021-04-09	2021-07-07
102		2021-07-07	2022-03-17
102		2022-03-17	NULL
103		2018-08-15	NULL
104		2019-05-15	NULL
105		2020-05-16	2022-07-25
105		2022-07-25	NULL
106		2021-04-15	2021-04-15
106		2021-04-15	NULL

在上述查询中:

ROW_NUMBER() 函数

在 SQL Server 中,ROW_NUMBER( ) 函数结合 OVER 子句用于为结果集中的行分配一个唯一的整数序号。
ROW_NUMBER( ) 函数的常见用法是将数据分组后,根据指定的排序方式为每个分组中的行分配一个序号。

语法:

sql 复制代码
ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2)

其中,PARTITION BY 指定了分组的列,而 ORDER BY 指定了排序的列。

sql 复制代码
row_number() over (partition by user_id order by date) as nextNum

上面的示例中,我们将结果集按 user_id 列进行分组,并按 date列进行排序。然后,为每个分组中的行分配一个唯一的整数序号,命名为 nextNum。

需要注意

<1> ROW_NUMBER( ) 函数是在 SELECT 查询的结果集上计算的,并不会对数据库中的实际数据进行更改。如果需要使用序号进行更新、删除等操作,可以将查询的结果作为子查询,并在外部查询中进行相关操作。

<2> ROW_NUMBER( ) 函数返回的序号是根据 ORDER BY 子句的排序顺序而确定的。如果 ORDER BY 子句中出现相同的值,结果可能会根据数据库引擎的具体实现而产生不确定的结果。如果需要确保排序的唯一性,请考虑在 ORDER BY 子句中使用更多的列来进行排序。

LEAD( ) 函数

在 SQL Server 中,LEAD( ) 函数用于在每一行中获取指定列的后一行的值。LEAD( ) 函数结合 OVER 子句可以对每个分组进行操作。

语法:

sql 复制代码
LEAD(column, offset, default value) OVER (PARTITION BY partition_column ORDER BY order_column)

column:指定要获取后一行值的列。

offset:可选参数,指定要获取的后一行的偏移量,默认为 1,即获取紧接着当前行的下一行的值。

default value:可选参数,在最后一行时用于提供默认值。

sql 复制代码
lead(date, 1) over (partition by user_id order by date) as nextdate

在查询中我们将结果集按 user_id 列进行分组,并按 date 列进行排序。然后使用 LEAD( ) 函数获取每个分组中当前行的下一个行的 date 列的值,将其命名为 nextdate。

需要注意

<1> LEAD( ) 函数的结果是基于指定的分组和排序顺序计算的。如果没有下一行或者超出了最后一行,LEAD( ) 函数根据提供的默认值返回 NULL。

<2>通过使用 LEAD( ) 函数,可以方便地获取指定列的后一行的值,这一点在很多情况都非常好用。

相关推荐
Dxy123931021615 分钟前
Python对字典列表按某个字段排序
开发语言·python
CF14年老兵18 分钟前
别被忽悠!从入门到年薪百万 AI 工程师的真实成长路径
python·aigc·openai
hkfkn1 小时前
Sql刷题日志(day6)
数据库·sql
寻丶幽风1 小时前
论文阅读笔记——ZeroGrasp: Zero-Shot Shape Reconstruction Enabled Robotic Grasping
论文阅读·笔记·深度学习·机器人·机械臂·具身智能
半青年2 小时前
单例模式:全局唯一性在软件设计中的艺术实践
java·c++·python·单例模式
fen_fen3 小时前
Miniconda Windows10版本下载和安装
python
柯西梦回黄鹤楼3 小时前
lmms-eval--微调实战笔记
笔记
kyle~3 小时前
深度学习---Pytorch概览
人工智能·pytorch·python·深度学习
老胖闲聊6 小时前
Python PyAutoGUI库【GUI 自动化库】深度解析与实战指南
python
闪电麦坤957 小时前
SQL:子查询(subqueries)
数据库·sql