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 进行递归查询?例如员工等级

sql server中的cte

在某些情况下,为什么CTE(公用表表达式)与SQL Server中的临时表相比会减慢查询速度

将 SQL Server 中的递归 CTE 转换为 netezza

在 SQL Server 数据库之间移动数据行是不是有比使用 CTE 更快的方法?

SQL Server 公用表表达式(CTE)实现递归