回答:
@ db2の答えを拡張したもの(読み取り:ゼロ)の手荒らし:
DECLARE @tb nvarchar(512) = N'dbo.[table]';
DECLARE @sql nvarchar(max) = N'SELECT * FROM ' + @tb
+ ' WHERE 1 = 0';
SELECT @sql += N' OR ' + QUOTENAME(name) + ' IS NULL'
FROM sys.columns
WHERE [object_id] = OBJECT_ID(@tb);
EXEC sys.sp_executesql @sql;
JNKのコメントに従って、すべての列をリストする必要があります。
WHERE c1 IS NULL OR c2 IS NULL OR c3 IS NULL
ただし、これを回避するためのやや効率の悪いアプローチは次のとおりです。
;WITH xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' AS ns)
SELECT *
FROM YourTable AS T1
WHERE (
SELECT T1.*
FOR XML PATH('row'), ELEMENTS XSINIL, TYPE
).exist('//*/@ns:nil') = 1
優れた組み込み構文はありませんが、Management Studioにはクエリを迅速に生成するための便利な機能がいくつかあります。
オブジェクトエクスプローラーで、目的のテーブルにドリルダウンして展開し、[列]フォルダー全体を空のクエリエディターにドラッグします。これにより、列のコンマ区切りリストがクエリに追加されます。
次に、検索と置換を開きます。「Find What」を,
「Replace With」にIS NULL OR
(先頭にスペースを付けて)設定し、Replace Allを押します。シーケンスの最後の1つを手動でクリーンアップする必要があります。
まだいですが、労働集約的ではありません。
複数の列をテストする必要がある場合は、次を使用できます。
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 =少なくとも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 =少なくとも1つの非NULLがあります
これがお役に立てば幸いです。
UNPIVOTは、列を行に変換します。プロセスでは、NULL値(reference)が削除されます。
与えられた入力
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以外の値をカウントできます。ソーステーブルの列の総数と比較すると、1つ以上の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
-IDに対して1で、UNPIVOTEDではありません
この値は、実行時にカタログテーブルを調べることで取得できます。
元の行は、結果に結合することで取得できます。
NULL以外の値を調査する場合は、where句に含めることができます。
...
) as unpvt
where ColValue <> '' -- will eliminate empty strings
これには、UNPIVOTを通じて運ばれる識別子が必要です。キーが最適です。存在しない場合は、ROW_NUMBER()ウィンドウ関数によって挿入できますが、これは実行に費用がかかる場合があります。
すべての列は、UNPIVOT句内に明示的にリストする必要があります。@ db2が示唆するように、SSMSを使用してそれらをドラッグできます。Aaron Bertrandの提案がそうであるように、テーブル定義が変化するときは動的ではありません。ただし、これはほとんどすべてのSQLに当てはまります。
かなり限られたデータセットの場合、実行計画はクラスター化インデックススキャンとストリーム集約です。これは、テーブルと多数のOR句を直接スキャンするよりもメモリが高価になります。