2012-04-20 13 views
16

Oldukça benzer bir sorgu üzerinde çalışıyorum şu: Ben gerçekte görmek istiyorum sonuç, beklendiği üzere olanSELECT DISTINCT'deki NULL'leri ortadan kaldırmanın en kolay yolu?

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 

çıktısı:

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

Yani, bir sütunda bazı kayıtlarda bir değer varsa ancak başkalarında değilse, o sütunda NULL ile satır atmak istiyorum. Ancak, bir sütun tüm kayıtlar için bir NULL değerine sahipse, bu NULL'u korumak istiyorum.

Tek bir sorguda bunu yapmanın en basit/en zarif yolu nedir?

Bir Cuma öğleden sonra bitmemiş olsaydım bunun basit olacağını hissediyorum.

+0

'a'' b' bir boş olmayan değerden daha fazla sütunun bir değere sahip miyim? Eğer durum buysa, iki değeri de almayı mı bekliyorsunuz? –

+0

Üzgünüm, bugün buna geri döndüm. Gruptaki tüm kayıtlar için, her sütun:% 100 tek bir değerle,% 100 NULL ile doldurulur veya kısmen tek bir değer ve kısmen NULL ile doldurulur. Örneğin: (1, 2, NULL), (1, 2, NULL), (1, NULL, NULL), (1, 2, NULL) olarak küçültülmelidir. –

cevap

8

bu deneyin:

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

Sen keman here alabilirsiniz. Ben değil, özellikle bu çözümün sevmiyorum

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

+1 çok başarılı –

+0

İkincisi, bu durumda ihtiyacım olanı yapar. Her sütun tamamen NULL, tamamen tek bir değerle doldurulur veya kısmen tek bir değer ve kısmen NULL ile doldurulur. MAX() problemi zarifçe çözer. Teşekkürler. –

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

Bu gerçekten çok tuhaf bir gereksinimdir. Acaba ihtiyacın var.

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

Well ama bana en uygun görünüyor: Yalnızca b bir boş olmayan bir değere sahip olabiliyorsa

Not bu basitleştiirlebilir .böylece, tam olarak ne JOIN SOL olsun gibi ne istediğinizi sizin açıklama sesler Not:

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

bu deneyin:

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

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

Sorgu:

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 

Çıktı:

X Y 
A B 
B NULL 

Canlı testi: http://sqlfiddle.com/#!3/259d6/16

DÜZENLEME

Mosty's answer görünce, benim kod basitleştirilmiş: Sadece CTE yaklaşım tercih

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 

, bu

yapabilirsiniz :-) daha kendini belgeleyen mantığı vardır Ayrıca, BTE olmayan bir yaklaşımla ilgili belgelerinizi de yazabilirsiniz:

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) 

Sonuç:

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

Lütfen çözümünüzün nasıl çalıştığına dair kısa bir açıklama ekleyebilir misiniz? –

İlgili konular