Підрахунок нульових і ненульових значень в одному запиті


141

У мене стіл

create table us
(
 a number
);

Зараз у мене є такі дані, як:

a
1
2
3
4
null
null
null
8
9

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


3
Привіт, де вам потрібен такий вид підрахунку коду бази даних, на якій мовній базі ми говоримо з найкращими побажаннями, Іордан
IordanTanev

2
Я здивований, що жодна відповідь не містить простого об'єднання підрахунку (*) ...
Lieven Keersmaekers

1
@Lieven: Чому б ти unionтут використовував ? Відповідь Монтерісто - це найкраще рішення.
Ерік

1
Тому що ОП хоче його за допомогою одного запиту. Відповідь Монтерісто насправді є найкращим рішенням ... йому просто потрібно додати союз :)
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метод.
Річард

4
Віддаю перевагу , count(*)щобcount(1)
Lei Чжао

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 лише в одному запиті ... Ви говорите, як це зробити за двома запитами ...
Romain Linsolas

@romaintaz: Цілком правильно. Я читаю заголовок як питання. За п’ять правок ніхто не думав це виправити. Так.
Ерік

@romaintaz: Так, ви праві, я сприйняв це як "запустити один раз запит, щоб визначити, скільки нулів у нас", я навіть не знаю, чому ^^ ', збираюся виправити, дякую.
Альберто Закканні

1
@Montecristo: Тому що в заголовку просили лише рахувати null:)
Ерік

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. Також, зробивши це таким чином, скануйте таблицю лише один раз; рішення UNION виконають два сканування таблиці. Не має значення для маленьких столиків, дуже важливих для величезних.
Філіп Келлі

2
Тільки зміни для SQL Server "Null values"повинні були стати 'Null values'. Одиночні цитати, а не парні.
Ерік

1
SQLServer використовує сканування індексу для цього запиту проти два індексу прагне , використовуючи з'єднання. У таблиці, що має 40 000 рядків, різниці в швидкості немає.
Лівен Кірсмейкерс

1
На таблиці з 11.332.581 рядками є два сканування таблиці , помітна різниця швидкостей (фактично, з'єднання трохи швидше).
Лівен Кірсмейкерс

1
Це не працювало для мене в Oracle 11g. Версія @ user155789 розмістила "case, коли a 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

У деяких тестуваннях на моїй системі коштує сканування повного столу.


4
Гарний підхід, чоловіче, подивись на плани виконання цих запитів. Ви знімаєте сканування таблиці вліво і вправо, особливо там, де є така кривава проста проста заява ( select count(*) from t where a is null), яка робить це.
Ерік

2
У мене немає зручної для пошуку бази даних, але або стовпець індексований, або ні. Якщо це так, це відбувається за допомогою діапазону сканування, в іншому випадку ви майже повністю скануєтеся на повну таблицю. В оракулі NULL не зберігаються в індексі, тому я підозрюю, що приклад не набагато кращий. Ваш пробіг може дуже.
EvilTeach

1
@EvilTeach: Індекси корисні лише тоді, коли ви не відтягуєте> ~ 10% рядків. Після цього починаються повні сканування. У цьому випадку ви отримаєте сканування принаймні один раз, якщо не два рази.
Ерік

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

Це трохи хитро. Припустимо, у таблиці є лише один стовпець, тоді 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 (*), механізм запиту рахує кількість рядків. Отже, результат підрахунку дорівнює 16. Але у випадку Count (empid) він підраховував не-NULL-значення у стовпці emid . Так ми отримали результат як 14.

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

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

буде рахувати як NULL, так і Non-NULL значення.

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


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 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 (СЛУЧАЙ, КОЛИ НУЛЬНИЙ ТАКІ 1 ELSE 0 END)
Владислав

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

Це нечітко, але він поверне єдиний запис з двома знаками, що вказує кількість нулів проти ненулевих.


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

Будуючи Альберто, я додав сукупність.

 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
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як цей код відповідає на питання, покращує його довгострокове значення.
Вішал Чходвані

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

для підрахунку ненульових значень

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

для підрахунку нульових значень

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

1
Оп попросив одинарний запит :)
infografnet

0

Я створив таблицю в postgres 10 і обидва наступні працювали:

select count(*) from us

і

select count(a is null) from us


a IS NULLвиробляє TRUEабо FALSE, і COUNT () буде рахувати всі значення НЕ НУЛЬ. Так 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,...

Відповідно до '...', це легко розширюється на більше стовпців, скільки потрібно


-1

Кількість елементів, де a є нульовим:

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

Кількість елементів, де а не є нульовим:

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

1
Питання - до одного запиту.
DreamWave
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.