Sql select 具有 Null 和 Not Null 值

Sql select with Null and Not Null values

我有一个 table 如下所示。

我想 select spec_id with language is not null。但是当 spec_id 除了 null 之外没有其他值时,我想 select 那个 spec_id 也具有 null 值。 例如。 Spec_id“170470”的语言为 'EN'。我想 select 只有语言行对于此 spec_id 不为空。而 spec_id '170464' 只有 Null 值。所以我也想 select 那一行。

我已尝试使用以下查询,但它 select 仅是语言中 NOT NULL 的情况。

   SELECT * from temp_value w1 
    where w1.NAC_ID = 2453 
    and w1.language is not null 
    or (w1.language is null and not exists (select spec_id from temp_value w2
                                        where w2.nac_id = 2453 
                                        and spec_id  in (select spec_id from temp_value 
                                                           where nac_id = 2453 and language is not null))
         and w1.nac_id = 2453);

我认为我们实际上可以通过使用 ROW_NUMBER:

来简化它
WITH cte AS (
    SELECT t.*, ROW_NUMBER() OVER (PARTITION BY spec_id ORDER BY language) rn
    FROM temp_value t
)

SELECT language, value, value_id, spec_id, language_id, nac_id
FROM cte
WHERE rn = 1;

这应该可行,因为 Oracle 默认将 NULL 排在最后。这意味着,对于每组 spec_id 记录,非 NULL 语言值将浮动到顶部(如果存在)。仅当给定的 spec_id 组没有非 NULL 语言记录时,才会选择 NULL 记录。

编辑:

为了解决可能有两个或多个非NULL语言记录的问题,按照之前的逻辑只保留一个NULL应该没有非NULL记录,我们可以试试:

WITH cte AS (
    SELECT t.*, ROW_NUMBER() OVER (PARTITION BY spec_id ORDER BY language) rn
    FROM temp_value t
)

SELECT language, value, value_id, spec_id, language_id, nac_id
FROM cte
WHERE language IS NOT NULL OR (rn = 1 AND language IS NULL);

你试过了吗:

 SELECT * from temp_value w1 
    where w1.NAC_ID = 2453 
    and w1.language is not null 
    or (w1.language is null and not exists 
           (select spec_id from temp_value w2
               where w2.nac_id = 2453 
               and w2.spec_id=w1.spec_id  
               and language is not null
            )
         );

还是我遗漏了什么?

您也可以只使用相关子查询:在子查询中您引用主查询的 table 别名。

select * from temp_value t
where language is not null
or language is null and not exists (select 'x'
                                    from temp_value
                                    where spec_id = t.spec_id
                                    and nac_id = t.nac_id
                                    and (language is not null
                                         or value is not null
                                         or language_id is not null));