これを試して:
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アプローチには、より自己文書化されたロジックがあります:-)
そうすることを意識している場合は、非 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)