SQL OVER(Partiton by) - 处理空值

Nat*_*ati 4 sql oracle null

我有以下情况:

表员工:

First Name | Last Name | Department | Salary
-----------|-----------|------------|---------
John       | Doe       | Finance    | 20
John       | Doe       | R&D        | 20
John       | null      | Finance    | 20
John       | long      | Finance    | 20
Run Code Online (Sandbox Code Playgroud)

我想要每行1个(名字,姓氏),除非我们在姓氏中有空,然后我只想要1行(名字,空)

对于上面的例子,结果是:

First Name | Last Name | Department | Salary
-----------|-----------|------------|---------
John       | null      | Finance    | 20
Run Code Online (Sandbox Code Playgroud)

但如果我没有那个记录,那么结果应该是:

First Name | Last Name | Department | Salary
-----------|-----------|------------|---------
John       | Doe       | R&D        | 20
John       | long      | Finance    | 20
Run Code Online (Sandbox Code Playgroud)

我想答案涉及到一些Partition By-s,但我不知道在哪里.

现在我来到这里:

SELECT FirstName,LastName, DEPARTMENT,Salary,RK FROM 
(
select * from 
    SELECT EXT.*, 
    ROW_NUMBER() OVER(PARTITION BY EXT.FirstName,EXT.LastName 
    ORDER BY rownum ASC) AS RK
      FROM Employees EXT   
)
WHERE RK = 1 ;
Run Code Online (Sandbox Code Playgroud)

谢谢 !

Ben*_*Ben 8

您的问题出在PARTITION子句中.除非至少有一个具有该名字的姓氏为NULL,否则您希望每个名字都有姓氏,在这种情况下,您只需要那些具有NULL姓氏的名字.

这里的答案是使用RANK()而不是ROW_NUMBER().RANK()不会创建连续列表; 相反,具有相等值的行获得相同的排名.

select firstname, lastname, department, salary, rk 
  from ( select a.*
              , rank() over ( partition by firstname
                                  order by case when lastname is null then 0 
                                                else 1 
                                           end
                                           ) as rnk
           from employees a
                )
where rnk = 1
Run Code Online (Sandbox Code Playgroud)

这通过使姓氏相关而不是姓氏本身来存在.

还有两点:

  1. 你有一个没有括号的嵌套选择.这不行.
  2. ROWNUM没有点订购.根据定义,rownum按语句返回的顺序返回行,这意味着行将始终按ROWNUM的顺序排列.