Contar valores nulos e não nulos em uma coluna

10

Como contar e recuperar nulos e não nulos na mesma coluna no MySQL?

minha mesa

---------------------------------------------------
id   |    name    |      visited   |   registDate |
---------------------------------------------------
1    |    george  |       NULL     |   2014-04-01 |
---------------------------------------------------
2    |    Thomas  |       NULL     |   2014-04-15 |
---------------------------------------------------
3    |    Wilfred |        1       |   2014-04-24 |
---------------------------------------------------
4    |    paul    |        1       |   2014-04-10 |
---------------------------------------------------
5    |    elina   |       NULL     |   2014-05-03 |
---------------------------------------------------
6    |    angela  |       NULL     |   2014-04-13 |
---------------------------------------------------
7    |    elina   |        1       |   2014-05-18 |
---------------------------------------------------

Resultado esperado

month      register    visited    not visited
---------------------------------------------
05-2014       2           1          1   
---------------------------------------------
04-2014       5           2          3
---------------------------------------------
santhosh
fonte

Respostas:

6

Tentar

SELECT 
   DATE_FORMAT(registDate, '%m-%Y') AS month,
   COUNT(name) AS register,
   SUM(!ISNULL(visited)) AS visited,
   SUM(ISNULL(visited)) AS not_visited
FROM mytable
GROUP BY DATE_FORMAT(registDate, '%m-%Y');

Não há necessidade de criar outra coluna.

Rodrigo Prazim
fonte
2

A primeira coisa a fazer é 'adicionar' uma coluna para o mês:

select *, date_format(registDate, '%Y-%m') as regist_month
from mytable

Então você pode obter todas as contagens:

select
  regist_month
, count(registDate) as count_registered
, sum(case when visited is not null then 1 else 0 end) as count_visited
, sum(case when visited is null then 1 else 0 end) as count_not_visited
from (
  select *, date_format(registDate, '%Y-%m') as regist_month
  from mytable
) group by regist_month
Yawar
fonte
Você pode usar contagem em vez de soma e encurtar a expressão um pouco: count(visited). count (<column>) contará apenas não nulos. Se você adicionar outro nível de aninhamento, count_not_visited pode ser determinado como:count_registered - count_visited
Lennart
1

Para contar todos os valores não nulos de uma coluna, digamos col1, você pode apenas usar count(col1) as cnt_col1. Mas, para ser mais óbvio, você pode usar a sum()função e o IS NOT NULLoperador devir sum(col1 IS NOT NULL). Isso IS NOT NULLocorre porque o operador retorna um int: 1 para true e 0 para false.

Para contar valores nulos, você pode usar o IS NULLoperador, que retorna 1 quando o valor nulo. Como antes, com o sum()operador.

Dado que, para obter o cadastro, a visitação e a não visitação de cada mês, é isso que você pode fazer:

SELECT
date_format(registDate, '%m-%Y') as month,
count(registDate) as register,
sum(visited is not null) as visited,
sum(visited is null) as 'not visited'
GROUP BY
date_format(registDate, '%m-%Y')

Observe que você pode exibir a coluna 'não visitado' com o espaço, apenas citando, citando duas vezes ou usando backticks (`).

Outra abordagem para selecionar e agrupar por mês seria concatenar mês com ano, assim concat(month(registDate), '-', date(registDate)). Mas é menos elegante.

O caseoperador proposto em outras respostas é perfeitamente válido, mas acho mais adequado para outras situações. E é mais detalhado.

Nuno Pereira
fonte