sql - validar - ¿Cómo devuelvo mis registros agrupados por NULL y NOT NULL?
saber si una variable es null en sql server (14)
Tengo una tabla que tiene una columna processed_timestamp
: si se ha procesado un registro, ese campo contiene la fecha y hora en que se procesó; de lo contrario, es nulo.
Quiero escribir una consulta que devuelva dos filas:
NULL xx -- count of records with null timestamps
NOT NULL yy -- count of records with non-null timestamps
¿Es eso posible?
Actualización: la tabla es bastante grande, por lo que la eficiencia es importante. Podría simplemente ejecutar dos consultas para calcular cada total por separado, pero quiero evitar golpear la mesa dos veces si puedo evitarlo.
Otra forma en T-sql (sql-server)
select count(case when t.timestamps is null
then 1
else null end) NULLROWS,
count(case when t.timestamps is not null
then 1
else null end) NOTNULLROWS
from myTable t
En MySQL puedes hacer algo como
SELECT
IF(ISNULL(processed_timestamp), ''NULL'', ''NOT NULL'') as myfield,
COUNT(*)
FROM mytable
GROUP BY myfield
En T-SQL (MS SQL Server), esto funciona:
SELECT
CASE WHEN Field IS NULL THEN ''NULL'' ELSE ''NOT NULL'' END FieldContent,
COUNT(*) FieldCount
FROM
TheTable
GROUP BY
CASE WHEN Field IS NULL THEN ''NULL'' ELSE ''NOT NULL'' END
Oráculo:
group by nvl2 (field, ''NOT NULL'', ''NULL'')
Otro método de MySQL es usar el operador CASE
, que se puede generalizar a más alternativas que IF()
:
SELECT CASE WHEN processed_timestamp IS NULL THEN ''NULL''
ELSE ''NOT NULL'' END AS a,
COUNT(*) AS n
FROM logs
GROUP BY a
Personalmente me gusta la solución de Pax, pero si absolutamente requiere que se devuelva una sola fila (como lo hice hace poco), en MS SQL Server 2005/2008 puede "apilar" las dos consultas usando un CTE
with NullRows (countOf)
AS
(
SELECT count(*)
FORM table
WHERE [processed_timestamp] IS NOT NULL
)
SELECT count(*) AS nulls, countOf
FROM table, NullRows
WHERE [processed_timestamp] IS NULL
GROUP BY countOf
Espero que esto ayude
Si es un oráculo, entonces puedes hacer:
select decode(field,NULL,''NULL'',''NOT NULL''), count(*)
from table
group by decode(field,NULL,''NULL'',''NOT NULL'');
Estoy seguro de que otros DB permiten un truco similar.
Stewart,
Tal vez considere esta solución. Es (también!) Vendedor no específico.
SELECT count([processed_timestamp]) AS notnullrows,
count(*) - count([processed_timestamp]) AS nullrows
FROM table
En cuanto a la eficiencia, esto evita 2x búsquedas de índice / escaneos de tabla / lo que sea al incluir los resultados en una fila. Si absolutamente requiere 2 filas en el resultado, dos pases sobre el conjunto pueden ser inevitables debido a los agregados de unión.
Espero que esto ayude
[T-SQL]:
select [case], count(*) tally
from (
select
case when [processed_timestamp] is null then ''null''
else ''not null''
end [case]
from myTable
) a
Y puede agregar en el enunciado caso cualquier otro valor que quiera formar una partición, por ejemplo, hoy, ayer, entre el mediodía y las 2 p. M., Después de las 6 p.m. del jueves.
Select Sum(Case When processed_timestamp IS NULL
Then 1
Else 0
End) not_processed_count,
Sum(Case When processed_timestamp Is Not NULL
Then 1
Else 0
End) processed_count,
Count(1) total
From table
Editar: no se leyó con cuidado, esta devuelve una sola fila.
En Oracle
SELECT COUNT(*), COUNT(TIME_STAMP_COLUMN)
FROM TABLE;
count (*) devuelve el recuento de todas las filas
count (column_name) devuelve el número de filas que no son NULL, por lo que
SELECT COUNT(*) - COUNT(TIME_STAMP_COLUMN) NUL_COUNT,
COUNT(TIME_STAMP_COLUMN) NON_NUL_COUNT
FROM TABLE
debería hacer el trabajo.
Si la columna está indexada, puede terminar con algún tipo de escaneo de rango y evitar leer la tabla.
Si su base de datos tiene una función COUNT (*) eficiente para una tabla, puede COUNT, el que sea menor, y restar.
Pruebe lo siguiente, es neutral del proveedor:
select
''null '' as type,
count(*) as quant
from tbl
where tmstmp is null
union all
select
''not null'' as type,
count(*) as quant
from tbl
where tmstmp is not null
Después de que nuestro gurú de DB2 local mire esto, él está de acuerdo: ninguna de las soluciones presentadas hasta la fecha (incluida esta) puede evitar un escaneo completo de la tabla (de la tabla si la marca de tiempo no está indexada, o del indexotherwise). Todos escanean cada registro en la tabla exactamente una vez.
Todas las soluciones CASE / IF / NVL2 () hacen una conversión nulo a cadena para cada fila, introduciendo una carga innecesaria en el DBMS. Esta solución no tiene ese problema.
SQL Server (comenzando en 2012):
SELECT IIF(ISDATE(processed_timestamp) = 0, ''NULL'', ''NON NULL''), COUNT(*)
FROM MyTable
GROUP BY ISDATE(processed_timestamp);