Подсчет нулевых и ненулевых значений в одном запросе

148

У меня есть стол

create table us
(
 a number
);

Теперь у меня есть такие данные:

a
1
2
3
4
null
null
null
8
9

Теперь мне нужен один запрос для подсчета нулевых, а не нулевых значений в столбце a

Эрик
источник
3
Привет, где вам нужен такой код
подсчетной
2
Я удивлен, что ни один ответ не содержит простого объединения выбранного количества (*) ...
Ливен Кеерсмэкерс,
1
@Lieven: С какой стати вы бы использовали unionздесь? Ответ Монтекристо - безусловно, лучшее решение.
Эрик,
1
Потому что OP хочет этого с помощью одного запроса. Ответ Монтекристо - безусловно, лучшее решение ... ему просто нужно добавить профсоюз :)
Ливен Кеерсмэкерс
1
Вот что я получаю, читая заголовок. Буду редактировать.
Эрик

Ответы:

235

Это работает для Oracle и SQL Server (возможно, вы сможете заставить его работать с другой СУБД):

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метод.
Ричард
4
Предпочитаю , count(*)чтобыcount(1)
Lei Чжао
67

Если я правильно понял, вы хотите подсчитать все 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 только в одном запросе ... Вы говорите, как это сделать в двух запросах ...
Ромен Линсолас
@romaintaz: Совершенно верно. Я прочитал заголовок как вопрос. За пять правок никто не подумал исправить. Ага.
Эрик
@romaintaz: Да, вы правы, я воспринял это как «запрос выполнить один раз, чтобы определить, сколько у нас нулей», я даже не знаю почему ^^ ', исправлю, спасибо.
Альберто Дзакканьи,
1
@Montecristo: Потому что название требует только подсчета null:)
Эрик,
44

Вот быстрая и грязная версия, которая работает в 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. Кроме того, в этом случае таблица будет сканироваться только один раз; решения UNION выполнят два сканирования таблицы. Неактуально для маленьких столиков, очень важно для больших.
Филип Келли,
2
Только изменение для SQL Server "Null values"должно стать 'Null values'. Одинарные кавычки, а не двойные.
Эрик
1
SQLServer использует сканирование индекса для этого запроса по сравнению с двумя поисками индекса с использованием объединения. На таблице с 40 000 строками нет разницы в скорости.
Ливен Кеерсмэкерс,
1
В таблице с 11.332.581 строками есть два сканирования таблицы , заметной разницы в скорости нет (на самом деле объединение происходит немного быстрее).
Ливен Кеерсмэкерс,
1
У меня это не сработало в Oracle 11g. Версия @ user155789, отправленная с "case when a is null then 1 else 0 end", была синтаксисом, который работал.
Стив
25

Насколько я понял ваш запрос, вы просто запускаете этот скрипт и получаете строки Total Null, Total NotNull,

select count(*) - count(a) as 'Null', count(a) as 'Not Null' from us;
Злобный хак
источник
23

для ненулевых

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

В некоторых случаях тестирования в моей системе требуется полное сканирование таблицы.

EvilTeach
источник
5
Хорошая подливка, чувак, посмотри на планы выполнения этих запросов. Вы запускаете сканирование таблицы слева и справа, особенно там, где select count(*) from t where a is nullэто делает такой чертовски простой оператор ( ).
Эрик
2
У меня нет удобной базы данных, но столбец либо проиндексирован, либо нет. Если это так, это происходит с помощью сканирования диапазона, в противном случае у вас в значительной степени остается полное сканирование таблицы. В oracle NULL не хранятся в индексе, поэтому я подозреваю, что ваш пример не намного лучше. Ваш пробег может очень.
EvilTeach
1
@EvilTeach: индексы полезны только тогда, когда вы не отбираете> ~ 10% строк. После этого запускается полное сканирование. В этом случае вы получите сканирование хотя бы один раз, если не дважды.
Эрик
20

обычно я использую этот трюк

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
elle0087
источник
Вам нужно поменять местами, count_notnullи count_nullтеперь он дает противоположные результаты :)
neu242
6

Это немного сложно. Предположим, что в таблице только один столбец, тогда 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 строк. из которых две строки равны NULL. Итак, когда мы используем Count (*), механизм запросов подсчитывает количество строк, поэтому мы получили результат count как 16. Но в случае Count (empid) он подсчитал значения, отличные от NULL в столбце empid. . Итак, мы получили результат 14.

поэтому всякий раз, когда мы используем COUNT (столбец), убедитесь, что мы позаботились о значениях NULL, как показано ниже.

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

будет считать как значения NULL, так и значения, отличные от NULL.

Примечание . То же самое применимо, даже если таблица состоит из более чем одного столбца. Count (1) даст общее количество строк независимо от значений NULL / Non-NULL. Только когда значения столбца подсчитываются с помощью Count (Column), нам нужно позаботиться о значениях NULL.

Santhoshkumar LM
источник
4

У меня была аналогичная проблема: подсчитывать все отдельные значения, считая нулевые значения за 1. В этом случае простой подсчет не работает, так как он не принимает во внимание нулевые значения.

Вот фрагмент, который работает с SQL и не требует выбора новых значений. В принципе, после выполнения отдельного запроса также верните номер строки в новом столбце (n) с помощью функции row_number (), а затем выполните подсчет в этом столбце:

SELECT COUNT(n)
FROM (
    SELECT *, row_number() OVER (ORDER BY [MyColumn] ASC) n
    FROM (
        SELECT DISTINCT [MyColumn]
                    FROM [MyTable]
        ) items  
) distinctItems
Старнуто ди топо
источник
3

Вот два решения:

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 
   SUM(ISNULL(a)) AS all_null,
   SUM(!ISNULL(a)) AS all_not_null
FROM us;

Просто!

Родриго Празим
источник
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 (CASE WHEN A IS NULL THEN 1 ELSE 0 END)
Владислав
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

Это странно, но он вернет одну запись с двумя столбцами, указывающими количество нулей и ненулевых значений.

C-Pound Guru
источник
1

Это работает в T-SQL. Если вы просто считаете количество чего-либо и хотите включить нули, используйте COALESCE вместо case.

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')
DaveX
источник
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
    ALL_VALUES
    ,COUNT(ALL_VALUES)
FROM(
        SELECT 
        NVL2(A,'NOT NULL','NULL') AS ALL_VALUES 
        ,NVL(A,0)
        FROM US
)
GROUP BY ALL_VALUES
Истиак Хоссейн
источник
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

если это 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
ТигрТигр
источник
0

На всякий случай, если вы хотите, чтобы это было в одной записи:

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

;-)

Sparhawk_
источник
0

для подсчета ненулевых значений

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

для подсчета нулевых значений

 select count(*) from us where a is null;
Deep Shah
источник
1
Оператор запросил единый запрос :)
infografnet
0

Я создал таблицу в postgres 10, и оба следующих действия сработали:

select count(*) from us

а также

select count(a is null) from us

Skrillybrick
источник
a IS NULLпроизводит TRUEили 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,...

В соответствии с "..." его легко расширить до большего количества столбцов, сколько нужно.

Vzzarr
источник
-1

Количество элементов, где a равно нулю:

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

Количество элементов, где a не равно нулю:

select count(a) from us where a is not null;
Ромен Линсолас
источник
1
Вопрос для одного запроса.
DreamWave