2012-04-20 36 views
16

我的查詢是相當類似的工作如下:最簡單的方法來消除SELECT DISTINCT中的空值?

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

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

SELECT DISTINCT a,b FROM #test 

DROP TABLE #test 

結果是,勿庸置疑,

a b 
------- 
A NULL 
A B 
B NULL 

輸出我想在現實中看到的是:

a b 
------- 
A B 
B NULL 

也就是說,如果一個列在某些記錄中有一個值,但在其他記錄中沒有,那麼我想要爲該列拋出NULL爲空的行。但是,如果列的所有記錄都有NULL值,我想保留該NULL。

在單個查詢中這樣做最簡單/最優雅的方式是什麼?

我有一種感覺,如果我在星期五的下午沒有精疲力竭,這將會很簡單。

+0

可以列的值'了'有比'B'一個非空值嗎?如果是這樣的話,你是否期望得到兩個值? – 2012-04-20 23:01:35

+0

對不起,我今天剛回來。對於組中的所有記錄,每列都是:100%填充單個值,100%填充NULL或部分填充單個值並部分填充NULL。例如:(1,2,NULL),(1,2,NULL),(1,NULL,NULL)應該減少爲(1,2,NULL)。 – 2012-04-23 14:23:57

回答

8

試試這個:

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

,您就能獲得小提琴here

注意,如果你只能有一個b非空值,這可以簡化爲:

select a, max(b) from test 
group by a 
+1

+1非常成功 – 2012-04-21 02:55:38

+0

第二個是我在這種情況下需要的。每列完全是NULL,完全由單個值填充,或者部分填充單個值並部分爲NULL。 MAX()優雅地解決了這個問題。謝謝。 – 2012-04-23 14:56:22

0
SELECT DISTINCT t.a, t.b 
FROM #test t 
WHERE b IS NOT NULL 
OR  NOT EXISTS (SELECT 1 FROM #test u WHERE t.a = u.a AND u.b IS NOT NULL) 
ORDER BY t.a, t.b 
0

這是一個非常奇怪的要求。我想知道你是如何需要它的。

SELECT DISTINCT a, b 
FROM test t 
WHERE NOT (b IS NULL 
      AND EXISTS 
       (SELECT * 
       FROM test ta 
       WHERE ta.a = t.a 
        AND ta.b IS NOT NULL 
       ) 
      ) 
    AND NOT (a IS NULL 
      AND EXISTS 
       (SELECT * 
       FROM test tb 
       WHERE tb.b = t.b 
        AND tb.a IS NOT NULL 
       ) 
      ) 
0

嘛,我特別不喜歡這樣的解決方案,但它似乎最適合我。請注意,你想要什麼描述聽起來完全像你的左得到的加入,令:

SELECT DISTINCT a.a, b.b 
FROM #test a 
    LEFT JOIN #test b ON a.a = b.a 
     AND b.b IS NOT NULL 
1

試試這個:

create table test(
x char(1), 
y char(1) 
); 

insert into test(x,y) values 
('a',null), 
('a','b'), 
('b', null), 
('b', null) 

查詢:

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 

輸出:

X Y 
A B 
B NULL 

現場測試:http://sqlfiddle.com/#!3/259d6/16

編輯

看到Mosty's answer,我簡化了我的代碼:

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 

我只是喜歡CTE方法,它有:-)

您可以將更多的自我記錄的邏輯如果您意識到這樣做,也將文檔放在非CTE方法上:

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
SELECT a,b FROM #test t where b is not null 
union 
SELECT a,b FROM #test t where b is null 
and not exists(select 1 from #test where a=t.a and b is not null) 

結果:

a b 
---- ---- 
A B 
B NULL 
1
;WITH CTE 
    AS 
    (
    SELECT DISTINCT * FROM #test 
    ) 
    SELECT a,b 
    FROM CTE   
    ORDER BY CASE WHEN b IS NULL THEN 9999 ELSE b END ; 
+0

您能否就您的解決方案的工作原理添加簡短的描述? – 2017-03-09 13:10:14