1つのクエリでnull値とnull以外の値をカウントする


141

テーブルがあります

create table us
(
 a number
);

今私は次のようなデータを持っています:

a
1
2
3
4
null
null
null
8
9

今、私はnullをカウントする単一のクエリを必要とし、 A列にNULLでない値を


3
こんにちは、あなたは私たちがよろしく、Iordan話しているどのような言語データベースに集計データベースのこの種のコードにどこが必要なのか
IordanTanev

2
単一の回答にselect count(*)の単純な結合が含まれていないことに驚いています...
Lieven Keersmaekers '08 / 08/13

1
@リーベン:どうしてunionここでここを使うの?モンテクリストの答えは断然最高のソリューションです。
エリック

1
OPは単一のクエリでそれを望んでいるからです。モンテクリストの答えは確かに最高の解決策です...彼はただユニオンを追加する必要があります:)
Lieven Keersmaekers

1
そして、それは私がタイトルを読むために得るものです。編集します。
エリック、

回答:


231

これはOracleおよびSQL Serverで機能します(別のRDBMSで機能させることができる場合があります)。

select sum(case when a is null then 1 else 0 end) count_nulls
     , count(a) count_not_nulls 
  from us;

または:

select count(*) - count(a), count(a) from us;

1
区別を使用count(*)してcount(a)もでうまく機能group by
シャノン

1
@shannon同意COUNT(a)します。追加するのに便利なコメントですが、これはスタックに応じて警告/エラーをスローし、コード内のコメントを保証する可能性があります。私はそのSUM方法を好みます。
Richard

4
優先count(*)count(1)
レイ趙

61

私が正しく理解していれば、列内のすべてのNULLとすべてのNOT NULLを数えたいと思います...

それが正しい場合:

SELECT count(*) FROM us WHERE a IS NULL 
UNION ALL
SELECT count(*) FROM us WHERE a IS NOT NULL

コメントを読んだ後、完全なクエリを持つように編集されました:]


SELECT COUNT(*), 'null_tally' AS narrative 
  FROM us 
 WHERE a IS NULL 
UNION
SELECT COUNT(*), 'not_null_tally' AS narrative 
  FROM us 
 WHERE a IS NOT NULL;

7
+1:はるかに単純で最も速い方法。すべての答えがこれではなかったとき、私はショックを受けました。
エリック、

6
はい、ありません。私は彼がNULLとNULL以外の数を1つのクエリだけで持つことを望んでいると思います... 2つのクエリでそれを行う方法を言っています...
Romain Linsolas

@romaintaz:なるほど。タイトルを質問として読みました。5つの編集で、誰もそれを修正することを考えていませんでした。イェッシュ。
エリック

@romaintaz:はい、そうです。これを「クエリを実行して、nullがいくつあるかを見つけるために1回実行する」と見なしました。なぜかはわかりません。^^ '訂正する予定です。ありがとうございます。
Alberto Zaccagni 2009

1
@モンテクリスト:タイトルは数えることだけを求めていたからですnull:)
Eric

42

以下は、Oracleで動作するダーティバージョンです。

select sum(case a when null then 1 else 0) "Null values",
       sum(case a when null then 0 else 1) "Non-null values"
from us

3
SQL Serverでも同様の構文が機能します。また、この方法でテーブルをスキャンするのは1回だけです。UNIONソリューションは2つのテーブルスキャンを実行します。小さなテーブルには関係なく、巨大なテーブルには非常に重要です。
フィリップケリー

2
SQL Serverのための唯一の変化はある"Null values"になることだろう'Null values'。二重引用符ではなく単一引用符。
エリック

1
SQLServerはこのクエリに対してインデックススキャンを使用しますが、ユニオンを使用して2つのインデックスシークを使用します。40.000行のテーブルでは、速度の違いはありません。
Lieven Keersmaekers、2009

1
11.332.581行のテーブルでは、2つのテーブルスキャンがあり、顕著な速度の違いはありません(実際には、ユニオンはわずかに高速です)。
Lieven Keersmaekers、2009

1
これは、Oracle 11gでは機能しませんでした。「aがnullの場合は1、その他の場合は0の末尾の場合」で投稿されたバージョン@ user155789が機能する構文でした。
Steve

25

クエリを理解したので、このスクリプトを実行してTotal Null、Total NotNull行を取得します。

select count(*) - count(a) as 'Null', count(a) as 'Not Null' from us;

23

null以外

select count(a)
from us

ヌル用

select count(*)
from us

minus 

select count(a)
from us

したがって

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

SELECT COUNT(*) - COUNT(A) NULLS
FROM US

仕事をすべき

列のタイトルが正しく表示されるという点で優れています。

SELECT COUNT(A) NOT_NULL, COUNT(*) - COUNT(A) NULLS
FROM US

私のシステムでのいくつかのテストでは、テーブル全体をスキャンする必要があります。


4
これらのクエリの実行計画をよく見てください。テーブルスキャンを左右に開始します。特に、これを実行するような流血の単純なステートメント(select count(*) from t where a is null)がある場合はそうです。
エリック、

2
調べるのに便利なデータベースはありませんが、列にインデックスが付けられているかどうかがわかりません。そうである場合は、範囲スキャンを介して行われます。それ以外の場合は、フルテーブルスキャンが残ります。Oracleでは、NULLはインデックスに格納されないので、例はそれほど良くないのではないかと思います。あなたの距離は非常にそうかもしれません。
EvilTeach 2009

1
@EvilTeach:インデックスは、行の10%を超えてプルバックしない場合にのみ役立ちます。その後、フルスキャンが開始されます。この場合、スキャンは2回ではなくても少なくとも1回は取得されます。
エリック

19

通常私はこのトリックを使います

select sum(case when a is null then 0 else 1 end) as count_notnull,
       sum(case when a is null then 1 else 0 end) as count_null
from tab
group by a


6

これは少しトリッキーです。テーブルの列が1つだけだとすると、Count(1)とCount(*)は異なる値になります。

set nocount on
    declare @table1 table (empid int)
    insert @table1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(NULL),(11),(12),(NULL),(13),(14);

    select * from @table1
    select COUNT(1) as "COUNT(1)" from @table1
    select COUNT(empid) "Count(empid)" from @table1

クエリ結果

画像からわかるように、最初の結果は、テーブルに16行あることを示しています。このうち2つの行はNULLです。したがって、Count(*)を使用すると、クエリエンジンは行数をカウントするため、カウント結果は16になります。しかし、Count(empid)の場合は、列empidの非NULL値をカウントしました。結果は14でした。

したがって、COUNT(Column)を使用するときは常に、以下に示すようにNULL値に注意してください。

select COUNT(isnull(empid,1)) from @table1

NULL値と非NULL値の両方をカウントします。

:テーブルが複数の列で構成されている場合でも、同じことが当てはまります。Count(1)は、NULLまたはNULL以外の値に関係なく、行の総数を示します。Count(Column)を使用して列の値がカウントされる場合のみ、NULL値を処理する必要があります。


4

同様の問題がありました。すべての個別の値をカウントし、null値も1としてカウントしました。この場合、null値が考慮されないため、単純なカウントは機能しません。

以下は、SQLで機能し、新しい値の選択を含まないスニペットです。基本的に、distinctを実行すると、row_number()関数を使用して新しい列(n)に行番号も返し、その列でカウントを実行します。

SELECT COUNT(n)
FROM (
    SELECT *, row_number() OVER (ORDER BY [MyColumn] ASC) n
    FROM (
        SELECT DISTINCT [MyColumn]
                    FROM [MyTable]
        ) items  
) distinctItems

3

2つのソリューションがあります。

Select count(columnname) as countofNotNulls, count(isnull(columnname,1))-count(columnname) AS Countofnulls from table name

または

Select count(columnname) as countofNotNulls, count(*)-count(columnname) AS Countofnulls from table name


3

これを試して..

SELECT CASE 
         WHEN a IS NULL THEN 'Null' 
         ELSE 'Not Null' 
       END a, 
       Count(1) 
FROM   us 
GROUP  BY CASE 
            WHEN a IS NULL THEN 'Null' 
            ELSE 'Not Null' 
          END 

2

MS SQL Serverを使用している場合...

SELECT COUNT(0) AS 'Null_ColumnA_Records',
(
    SELECT COUNT(0)
    FROM your_table
    WHERE ColumnA IS NOT NULL
) AS 'NOT_Null_ColumnA_Records'
FROM your_table
WHERE ColumnA IS NULL;

これを行うことはお勧めしません...しかし、ここにあります(結果として同じテーブルにあります)


2

ISNULL埋め込み関数を使用します。



これも価値のある答えです。私は個人的に、COUNT(DISTINCT ISNULL(A、 ''))がCOUNT(DISTINCT A)+ SUM(AがNULLの場合1 ELSE 0 ENDの場合)よりもうまく機能することを発見しました
Vladislav

1

mysqlの場合、このようなことを試すことができます。

select 
   (select count(*) from TABLENAME WHERE a = 'null') as total_null, 
   (select count(*) from TABLENAME WHERE a != 'null') as total_not_null
FROM TABLENAME

1
SELECT SUM(NULLs) AS 'NULLS', SUM(NOTNULLs) AS 'NOTNULLs' FROM 
    (select count(*) AS 'NULLs', 0 as 'NOTNULLs' FROM us WHERE a is null
    UNION select 0 as 'NULLs', count(*) AS 'NOTNULLs' FROM us WHERE a is not null) AS x

あいまいですが、nullと非nullの数を示す2つのcolsを持つ単一のレコードを返します。


1

これはT-SQLで機能します。何かの数を数えるだけで、ヌルを含めたい場合は、大文字小文字の代わりにCOALESCEを使用します。

IF OBJECT_ID('tempdb..#us') IS NOT NULL
    DROP TABLE #us

CREATE TABLE #us
    (
    a INT NULL
    );

INSERT INTO #us VALUES (1),(2),(3),(4),(NULL),(NULL),(NULL),(8),(9)

SELECT * FROM #us

SELECT CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END AS 'NULL?',
        COUNT(CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END) AS 'Count'
    FROM #us
    GROUP BY CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END

SELECT COALESCE(CAST(a AS NVARCHAR),'NULL') AS a,
        COUNT(COALESCE(CAST(a AS NVARCHAR),'NULL')) AS 'Count'
    FROM #us
    GROUP BY COALESCE(CAST(a AS NVARCHAR),'NULL')

1

Albertoをベースにして、ロールアップを追加しました。

 SELECT [Narrative] = CASE 
 WHEN [Narrative] IS NULL THEN 'count_total' ELSE    [Narrative] END
,[Count]=SUM([Count]) FROM (SELECT COUNT(*) [Count], 'count_nulls' AS [Narrative]  
FROM [CrmDW].[CRM].[User]  
WHERE [EmployeeID] IS NULL 
UNION
SELECT COUNT(*), 'count_not_nulls ' AS narrative 
FROM [CrmDW].[CRM].[User] 
WHERE [EmployeeID] IS NOT NULL) S 
GROUP BY [Narrative] WITH CUBE;


1
select count(isnull(NullableColumn,-1))

2
このコードは質問に答えることがありますが、このコードが質問に答える理由や方法に関する追加のコンテキストを提供すると、長期的な価値が向上します。
Vishal Chhodwani

1

答えはすべて間違っているか、非常に古くなっています。

このクエリを実行する簡単で正しい方法は、COUNT_IF関数を使用することです。

SELECT
  COUNT_IF(a IS NULL) AS nulls,
  COUNT_IF(a IS NOT NULL) AS not_nulls
FROM
  us

0

単一のレコードにしたい場合に備えて:

select 
  (select count(*) from tbl where colName is null) Nulls,
  (select count(*) from tbl where colName is not null) NonNulls 

;-)


0

null以外の値をカウントするため

select count(*) from us where a is not null;

null値をカウントするため

 select count(*) from us where a is null;

1
opは単一のクエリを要求しました:)
infografnet

0

私はpostgres 10でテーブルを作成し、以下の両方が機能しました:

select count(*) from us

そして

select count(a is null) from us


a IS NULLTRUEまたはを生成しFALSE、COUNT()はすべてのNOT NULL値をカウントします。したがってcount(a is null)、すべての行の数を返します。
ypresto

0

私の場合、私は複数の列の間の「ヌル分布」を望みました:

SELECT
       (CASE WHEN a IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS a_null,
       (CASE WHEN b IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS b_null,
       (CASE WHEN c IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS c_null,
       ...
       count(*)
FROM us
GROUP BY 1, 2, 3,...
ORDER BY 1, 2, 3,...

「...」のとおり、必要に応じて、より多くの列に簡単に拡張できます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.