在一行中查找重复项

3
我有一个名为TEST的表。一些字段具有空值。
Country City   Street   House
US      NULL   Avenue   14
UK      London NULL     15
NULL    NULL   NULL     NULL
NULL    NULL   Central  16

我需要显示只有一个NULL的项目。
因此输出应为:
Country City   Street House
US      NULL   Avenue 14
UK      London NULL   15

我有一个比较愚蠢的解决方案,就是比较所有可能的列对并检查是否为空。
就像这样:
 SELECT * FROM TEST
 WHERE NOT (
 (country='NULL' AND city='NULL')
 OR (country='NULL' AND street='NULL')
 OR (coutry='NULL' AND house='NULL')
 OR (city='NULL' AND street='NULL')
 OR (city='NULL' AND house='NULL')
 OR (street='NULL' AND house='NULL')
 )

它可以工作,但要了解这是非常低效的。

你能推荐更加优雅的解决方案吗?


2
仅供参考:我认为你的条件应该使用形式为country IS NULL而不是country = 'NULL',因为null不是一个字符串,而是一个非常特殊的值。您还应该在标签中明确说明您使用的是mysql还是ms sql,它们具有不同的语法。 - Asenar
你使用哪个数据库管理系统? - user330315
2个回答

4
select * from TEST
WHERE  
  CASE WHEN country = 'NULL' THEN 1 ELSE 0 END
+ CASE WHEN city= 'NULL' THEN 1 ELSE 0 END
+ CASE WHEN Street = 'NULL' THEN 1 ELSE 0 END
+ CASE WHEN House = 'NULL' THEN 1 ELSE 0 END = 1

好主意,但我会测试如果总和 < 2,而不是 = 1 - Florin Ghita
4
我认为应该是 when country IS NULL 而不是字符串比较。 - user330315
我同意@FlorinGhita的观点,= 1将消除所有没有NULL值的行。 - Akanksha Singh
<2 不会带来任何优势,如果 NULL 记录的计数为 0,它也会选择记录。 <2 是与 = 1 不同的条件。如果您仔细阅读问题,他想列出具有一个空值而不是零个空值的记录。 - Cato
IS NULL是ISO/ANSI首选的方法,但提问者使用的是= 'NULL',在某些SQL版本中仍然可以使用。 - Cato

0
select *
from test1 
where
length(nvl(country,'@')||nvl(City,'@')||nvl(street,'@')||nvl(house,'@'))-
length(replace(nvl(country,'@')||nvl(City,'@')||nvl(street,'@')||nvl(house,'@'),'@',null))=1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接