Answers:
如果需要测试多列,则可以使用以下内容:
Column_1 Column_2 Column_3
-------- -------- --------
1 2 NULL
1 NULL NULL
5 6 NULL
首先,测试NULL并计数:
select
sum(case when Column_1 is null then 1 else 0 end) as Column_1,
sum(case when Column_2 is null then 1 else 0 end) as Column_2,
sum(case when Column_3 is null then 1 else 0 end) as Column_3,
from TestTable
产生NULL计数:
Column_1 Column_2 Column_3
0 1 3
如果结果为0,则没有NULL。
其次,让我们计算非NULL:
select
sum(case when Column_1 is null then 0 else 1 end) as Column_1,
sum(case when Column_2 is null then 0 else 1 end) as Column_2,
sum(case when Column_3 is null then 0 else 1 end) as Column_3,
from TestTable
...但是由于我们在这里计算非NULL,因此可以简化为:
select
count(Column_1) as Column_1,
count(Column_2) as Column_2,
count(Column_3) as Column_3,
from TestTable
任一都会产生:
Column_1 Column_2 Column_3
3 2 0
如果结果为0,则该列完全由NULL组成。
最后,如果只需要检查特定的列,那么TOP 1会更快,因为它应该在第一次命中时停止。然后,您可以选择使用count(*)给出布尔样式的结果:
select top 1 'There is at least one NULL' from TestTable where Column_3 is NULL
select count(*) from (select top 1 'There is at least one NULL' AS note from TestTable where Column_3 is NULL) a
0 =没有NULL,1 =至少有一个NULL
要么
select top 1 'There is at least one non-NULL' AS note from TestTable where Column_3 is not NULL
select count(*) from (select top 1 'There is at least one non-NULL' AS note from TestTable where Column_3 is not NULL) a
0 =它们全为NULL,1 =至少有一个非NULL
我希望这有帮助。
UNPIVOT将列转换为行。在此过程中,将消除NULL值(参考)。
给定输入
create table #t
(
ID int primary key,
c1 int null,
c2 int null
);
insert #t(id, c1, c2)
values
(1, 12, 13),
(2, null, 14),
(3, 15, null),
(4, null, null);
UNPIVOT查询
select
ID, ColName, ColValue
from
(
select *
from #t
) as p
unpivot
(
ColValue for ColName in
(c1, c2) -- explicit source column names required
) as unpvt;
将产生输出
| ID | ColName | ColValue |
|----|---------|----------|
| 1 | c1 | 12 |
| 1 | c2 | 13 |
| 2 | c2 | 14 |
| 3 | c1 | 15 |
可悲的是,第4行已被完全消除,因为它只有NULL!可以通过将伪值注入源查询中来方便地重新引入它:
select
ID, ColName, ColValue
from
(
select
-5 as dummy, -- injected here, -5 is arbitrary
*
from #t
) as p
unpivot
(
ColValue for ColName in
(dummy, c1, c2) -- referenced here
) as unpvt;
通过汇总ID上的行,我们可以计算非null值。与源表中的列总数进行比较,将确定包含一个或多个NULL的行。
select
ID
from
(
select -5 as dummy, *
from #t
) as p
unpivot
(
ColValue for ColName in
(dummy, c1, c2)
) as unpvt
group by ID
having COUNT(*) <> 3;
我将3作为
源表#t中的列数
+ 1用于注入的虚拟列
-1用于ID,这不是UNPIVOTED
该值可以在运行时通过检查目录表获得。
可以通过加入结果来检索原始行。
如果要调查非NULL值,则可以将它们包含在where子句中:
...
) as unpvt
where ColValue <> '' -- will eliminate empty strings
这需要通过UNPIVOT携带的标识符。一把钥匙是最好的。如果不存在,则可以通过ROW_NUMBER()窗口函数注入一个,尽管执行起来可能会很昂贵。
所有列必须在UNPIVOT子句中明确列出。可以使用SSMS将它们拖入,如@ db2所示。当表定义改变时,它不会是动态的,就像Aaron Bertrand的建议那样。但是,几乎所有SQL都是这种情况。
对于我的有限数据集,执行计划是聚簇索引扫描和流聚合。与直接扫描表和许多OR子句相比,这将花费更多的内存。