【问题标题】:Sql select with Null and Not Null values带有 Null 和 Not Null 值的 Sql 选择
【发布时间】:2023-03-27 02:19:01
【问题描述】:

我有一张如下表。

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

我已尝试使用以下查询,但它仅选择语言中 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);

【问题讨论】:

    标签: sql select null oracle12c exists


    【解决方案1】:

    我认为我们实际上可以通过使用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);
    

    【讨论】:

    • 嗨,我试过了。这适用于这种情况,但是一个 spec_id 有更多的语言,例如。对于 spec_id 170470,如果有两种语言,如 EN 和 DE,那么它只选择第 1 行的值。
    • @newintodev 当然,检查我刚刚添加到答案中的第二个查询。
    【解决方案2】:

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

    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));
    

    【讨论】:

      【解决方案3】:

      你试过了吗:

       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
                  )
               );
      

      还是我错过了什么?

      【讨论】:

        猜你喜欢
        • 2016-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-14
        • 2014-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多