Sql 如果列不为空,请为不同的列选择多行,否则请选择列为空的第一行

Sql 如果列不为空,请为不同的列选择多行,否则请选择列为空的第一行,sql,oracle,Sql,Oracle,我需要执行一个有趣的查询。对于下表A,我想为distinctuserId选择所有非空phoneNumber,但如果distinctuserId不存在非空phoneNumber值,则为distinctuserId选择仅一个nullphoneNumber 表A | id | userId | phoneNumber | emailAddress | ------------------------------------------- | 1 | 1 | 0123456789 |

我需要执行一个有趣的查询。对于下表A,我想为distinctuserId选择所有非空phoneNumber,但如果distinctuserId不存在非空phoneNumber值,则为distinctuserId选择仅一个nullphoneNumber

表A

| id | userId | phoneNumber | emailAddress | 
 ------------------------------------------- 
| 1  |   1    | 0123456789  |     null     | 
| 2  |   1    | 1234567890  |     null     | 
| 3  |   1    |    null     |  test@gmail  | 
| 4  |   2    |    null     |  andy@yahoo  | 
| 5  |   2    |    null     |  andy@gmail  |
预期结果

| id | userId | phoneNumber | emailAddress |
-------------------------------------------
| 1  |   1    | 0123456789  |     null     |
| 2  |   1    | 1234567890  |     null     |
| 5  |   2    |    null     |  andy@gmail  |
我在下面编写了查询,它返回了所需的结果,但我想看看是否有更好、更优化的方法来实现这一点。而不是编写多个子查询

SELECT * 
FROM A 
WHERE phoneNumber IS NOT NULL 
UNION 
SELECT * 
FROM A 
WHERE id IN (SELECT MAX(id) 
             FROM A WHERE phoneNumber IS NULL 
                AND userId NOT IN (SELECT userId 
                                   FROM A 
                                   WHERE phoneNumber IS NOT NULL) 
             GROUP BY userId)

您可以使用
COUNT()
ROW\u NUMBER()
分析函数:

SELECT *
FROM   (
  SELECT A.*,
         COUNT( phoneNumber) OVER ( PARTITION BY userId ) AS ct,
         ROW_NUMBER() OVER ( PARTITION BY userId ORDER BY id DESC ) AS rn
  FROM   A
)
WHERE  phoneNumber IS NOT NULL
OR     ( ct = 0 AND rn = 1 );

考虑到你的代码已经达到了预期的结果,这个问题可能更适合:)那么:如果一个ID至少有一个非空电话号码,你必须返回不同的非空电话号码?也就是说,对于每个不同的非空电话号码,只需选择其中一行(id、phonenumber)(以其碰巧拥有的电子邮件地址为准)?如果一个id的所有电话号码都是空的,那么只需为该id选择一行(任意一行)?