Easiest way to eliminate NULLs in SELECT DISTINCT?

前端 未结 8 539
我寻月下人不归
我寻月下人不归 2020-12-10 01:28

I am working on a query that is fairly similar the following:

CREATE TABLE #test (a char(1), b char(1))

INSERT INTO #test(a,b) VALUES 
(\'A\',NULL),
(\'A\',         


        
相关标签:
8条回答
  • 2020-12-10 02:00

    Try this:

    select distinct * from test
    where b is not null or a in (
      select a from test
      group by a
      having max(b) is null)
    

    You can get the fiddle here.

    Note if you can only have one non-null value in b, this can be simplified to:

    select a, max(b) from test
    group by a
    
    0 讨论(0)
  • 2020-12-10 02:03

    Try this:

    create table test(
    x char(1),
    y char(1)
    );
    
    insert into test(x,y) values
    ('a',null),
    ('a','b'),
    ('b', null),
    ('b', null)
    

    Query:

    with has_all_y_null as
    (
        select x
        from test
        group by x
        having sum(case when y is null then 1 end) = count(x)
    )
    select distinct x,y from test
    where 
    
        (
            -- if a column has a value in some records but not in others,
            x not in (select x from has_all_y_null) 
    
            -- I want to throw out the row with NULL
            and y is not null 
        )
        or 
        -- However, if a column has a NULL value for all records, 
        -- I want to preserve that NULL
        (x in (select x from has_all_y_null))
    
    order by x,y
    

    Output:

     X    Y
     A    B
     B    NULL
    

    Live test: http://sqlfiddle.com/#!3/259d6/16

    EDIT

    Seeing Mosty's answer, I simplified my code:

    with has_all_y_null as
    (
        select x
        from test
        group by x
    
        -- having sum(case when y is null then 1 end) = count(x) 
        -- should have thought of this instead of the code above. Mosty's logic is good:
        having max(y) is null
    )
    select distinct x,y from test
    where 
        y is not null
        or 
        (x in (select x from has_all_y_null))
    order by x,y
    

    I just prefer CTE approach, it has a more self-documenting logic :-)

    You can also put documentation on non-CTE approach, if you are conscious of doing so:

    select distinct * from test
    where b is not null or a in 
      ( -- has all b null
      select a from test
      group by a
      having max(b) is null)
    
    0 讨论(0)
提交回复
热议问题