Contar valores nulos y no nulos en una columna

10

¿Cómo contar y recuperar nulo y no nulo en la misma columna en MySQL?

mi 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
fuente

Respuestas:

6

Tratar

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');

No es necesario crear otra columna.

Rodrigo Prazim
fuente
2

Lo primero que debe hacer es 'agregar' una columna para el mes:

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

Entonces puedes obtener todos los recuentos:

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
fuente
Se puede utilizar en lugar de recuento suma y acortar la expresión un poco: count(visited). count (<column>) solo contará no es nulo. Si agrega otro nivel de anidamiento, count_not_visited se puede determinar comocount_registered - count_visited
Lennart
1

Para contar todos los valores no nulos para una columna, por ejemplo col1, solo puede usar count(col1) as cnt_col1. Pero, para ser más obvio, puede usar la sum()función y el IS NOT NULLoperador, convirtiéndose sum(col1 IS NOT NULL). Esto se debe a que el IS NOT NULLoperador devuelve un int: 1 para verdadero y 0 para falso.

Para contar valores nulos, puede usar el IS NULLoperador, que devuelve 1 cuando el valor es nulo. Como antes, con el sum()operador.

Dado que, para obtener lo registrado, visitado y no visitado por cada mes, esto es lo que puede hacer:

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')

Tenga en cuenta que puede generar la columna 'no visitado' con el espacio, simplemente citando, citando dos veces o usando las teclas de retroceso (`).

Otro enfoque para seleccionar y agrupar por mes sería concatenar mes con año, como este concat(month(registDate), '-', date(registDate)). Pero es menos elegante.

El caseoperador propuesto en otras respuestas es perfectamente válido, pero creo que es más adecuado para otras situaciones. Y es más detallado.

Nuno Pereira
fuente