题目描述
(通过次数317 | 提交次数446,通过率71.08%)
表: CoffeeShop +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | drink | varchar | +-------------+---------+ id 是该表的主键。 该表中的每一行都显示了订单 id 和所点饮料的名称。一些饮料行为 null。 编写一个 SQL 查询,将 drink 的 null值替换为前面最近一行不为 null的 drink。保证表第一行的 drink 不为 null。 返回与输入顺序相同的结果表。 查询结果格式示例如下。 示例 1: 输入: CoffeeShop 表: +----+------------------+ | id | drink | +----+------------------+ | 9 | Mezcal Margarita | | 6 | null | | 7 | null | | 3 | Americano | | 1 | Daiquiri | | 2 | null | +----+------------------+ 输出: +----+------------------+ | id | drink | +----+------------------+ | 9 | Mezcal Margarita | | 6 | Mezcal Margarita | | 7 | Mezcal Margarita | | 3 | Americano | | 1 | Daiquiri | | 2 | Daiquiri | +----+------------------+ 解释: 对于 ID 6,之前不为空的值来自 ID 9。我们将 null 替换为 “Mezcal Margarita”。 对于 ID 7,之前不为空的值来自 ID 9。我们将 null 替换为 “Mezcal Margarita”。 对于 ID 2,之前不为空的值来自 ID 1。我们将 null 替换为 “Daiquiri”。 请注意,输出中的行与输入中的行相同。 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/change-null-values-in-a-table-to-the-previous-value
//测试数据 Create table If Not Exists CoffeeShop (id int, drink varchar(20)); insert into CoffeeShop (id, drink) values ('9', 'Mezcal Margarita'); insert into CoffeeShop (id, drink) values ('6', 'None'); insert into CoffeeShop (id, drink) values ('7', 'None'); insert into CoffeeShop (id, drink) values ('3', 'Americano'); insert into CoffeeShop (id, drink) values ('1', 'Daiquiri'); insert into CoffeeShop (id, drink) values ('2', 'None');
解题思路
这道题出的不是很严谨。
示例中给出了CoffeeShop表的几条样例数据,然后要求以样例数据的顺序来判断某条数据的上一条数据。
实际上,数据在数据库中存储时是无序的,如果不明确指定排序规则,SQL语句多次执行的顺序可能是不一样的。
如果需要明确的查出某条数据的前一条,必须先以一个明确的排序规则编出序号。显然根据题目描述,本题是没有一个明确的排序规则的。
当然,不是说没有明确的排序规则就无法排序,而是说下面同样的SQL,多次执行,可能排序结果不一样。
select id, drink, row_number() over() rn from CoffeeShop;
抛开这个问题不谈,题目本身怎么解决呢?
假如,我们知道了每一行的排序序号,那么根据题目描述,如果当前行的drink为空,则需要返回上一个不为空的值。
也就是说,返回从当前行向前数,第一个drink的值不为空的行的drink值。
这里可以使用自关联来实现。
最后,再开窗排序,获取每行最近一个drink不为空的值即可。
参考SQL
未特别说明的情况下,参考SQL为基于MySQL8.0实现。
with tmp as ( select id, drink, row_number() over() rn from CoffeeShop ) select c.id, c.drink from ( select a.id, coalesce(a.drink,b.drink) drink, a.rn, row_number() over(partition by a.id order by b.rn desc) rn2 from tmp a left join tmp b on a.rn > b.rn and b.drink is not null )c where c.rn2 = 1 order by c.rn;
本站所有内容均为原创,本站保留所有权利。仅允许非商业用途的转载,但必须注明来源网站、作者、来源链接!否则,由此造成的一切后果,由转载方承担!
干货分享、技术提升、面试笔试、学习交流,欢迎关注公众号:xuesql。QQ学习交流群:209942678。