sql server中的CTE返回空值但不是NULL问题
Posted
技术标签:
【中文标题】sql server中的CTE返回空值但不是NULL问题【英文标题】:CTE in sql server return empty value but not NULL issue 【发布时间】:2021-02-06 22:38:07 【问题描述】:这是一个经典问题:编写一个 SQL 查询,从 Employee 表中获取第二高的薪水。
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
例如,给定上面的 Employee 表,查询应该返回 200 作为第二高的薪水。如果没有第二高的薪水,则查询应返回 null。
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
我在 SQL server 中使用 CTE 来解决这个问题:
with Emp_Rank AS
(select Salary, row_number()over(order by Salary) as Salrank
from Employee)
Select Salary as SecondHighestSalary
from Emp_Rank
where Emp_Rank.Salrank = 2
答案不被接受,如下图所示。我认为 [] vs [null] 是问题,但我不知道为什么或如何解决它。
输入 "headers": "Employee": ["Id", "Salary"], "rows": "Employee": [[1, 100]] 输出 “标题”:[“SecondHighestSalary”],“值”:[] 预期的 "headers":["SecondHighestSalary"],"values":[[null]]
Ps,我使用 Max() 来解决这个问题没有问题。 null 在那里不是问题。 (为什么?)
非常感谢您的宝贵时间。
【问题讨论】:
【参考方案1】:我很欣赏 GMB 所提供的,就这两种解决方案而言,problem 的测试用例都失败了。
with sal(salary, rnk) as
(select salary,dense_rank() over( order by Salary desc ) as rnk from Employee)
select max(salary) as SecondHighestSalary from sal where rnk=2;
这里的技巧是:当没有行可供选择时,MAX 返回 NULL。 有适用于 mysql 的 case 语句的解决方案,但使用 t-sql 就很棘手。
select nullif(salary,'') as SecondHighestSalary from sal where rnk=2;
理想情况下,这应该可以,但它似乎代表空白,' ' 是不够的。许多人使用 count 函数来解决问题,它只是在底层做一些分析性的双重计算,类似于 max() 所做的。
非常高兴,如果有人可以解决这个问题。
【讨论】:
【参考方案2】:您的尝试对我来说看起来不错 - 您只需按降序而不是升序排列薪水:
with emp_rank as (
select salary, row_number()over(order by salary desc) as salrank
from employee
)
select salary as secondhighestsalary
from emp_rank
where salrank = 2
根据您希望如何处理平局,您可能希望使用 dense_rank()
而不是 row_number()
(这将返回第二个不同的最高值,即使在第一个或第二个位置存在平局)。
如果您不关心平局,请注意,您可以使用fetch
子句以更简单的方式获得相同的结果:
select salary as secondhighestsalary
from employee
order by salary desc
offset 1 row fetch next 1 row only
【讨论】:
非常感谢您提供更简单的方式!我在我的代码中添加了 desc 但它仍然返回错误。认为它期望 [null] 作为输出。知道为什么吗?以上是关于sql server中的CTE返回空值但不是NULL问题的主要内容,如果未能解决你的问题,请参考以下文章
Presto SQL 是不是像 SQL Server 一样支持使用 CTE 进行递归查询?例如员工等级
在某些情况下,为什么CTE(公用表表达式)与SQL Server中的临时表相比会减慢查询速度
将 SQL Server 中的递归 CTE 转换为 netezza