Estoy intentando ordenar por fecha. Quiero que las fechas más recientes aparezcan primero. Eso es bastante fácil, pero hay muchos registros que son nulos y vienen antes de cualquier registro que tenga una fecha.
He intentado algunas cosas sin éxito:
ORDER BY ISNULL(Next_Contact_Date, 0)
ORDER BY ISNULL(Next_Contact_Date, 999999999)
ORDER BY coalesce(Next_Contact_Date, 99/99/9999)
¿Cómo puedo ordenar por fecha y que los nulos sean los últimos? El tipo de datos es smalldatetime
.
sql-server
sql-server-2005
tsql
UpHelix
fuente
fuente
Respuestas:
smalldatetime
tiene un rango hasta el 6 de junio de 2079, por lo que puede usarSi no hay registros legítimos tendrá esa fecha.
Si esta no es una suposición, le gustaría confiar en una opción más sólida: ordenar en dos columnas.
ORDER BY CASE WHEN Next_Contact_Date IS NULL THEN 1 ELSE 0 END, Next_Contact_Date
Sin embargo, ambas sugerencias anteriores no pueden utilizar un índice para evitar una clasificación y ofrecen planes de apariencia similar.
Otra posibilidad si existe tal índice es
SELECT 1 AS Grp, Next_Contact_Date FROM T WHERE Next_Contact_Date IS NOT NULL UNION ALL SELECT 2 AS Grp, Next_Contact_Date FROM T WHERE Next_Contact_Date IS NULL ORDER BY Grp, Next_Contact_Date
fuente
VARCHAR
campos (pORDER BY ISNULL(my_varchar, 'ZZZZZZ')
. Ej. ) Y es extremadamente útil, especialmente para obtener pedidos de cierta manera cuando se usaGROUP BY . . . GROUPING SETS
. Gracias por publicar esto.Según Itzik Ben-Gan, autor de T-SQL Fundamentals para MS SQL Server 2012 , "De forma predeterminada, SQL Server ordena las marcas NULL antes que los valores no NULL . Para que las marcas NULL clasifiquen en último lugar, puede usar una expresión CASE que devuelva 1 cuando la columna " Next_Contact_Date es NULL " y 0 cuando no es NULL . Las marcas que no son NULL obtienen 0 de la expresión; por lo tanto, se clasifican antes que las marcas NULL (que obtienen 1). Esta expresión CASE se usa como la primera ordenar columna ". el Next_Contact_Datecolumn "debe especificarse como la segunda columna de clasificación. De esta forma, las marcas que no son NULL se clasifican correctamente entre sí". Aquí está la consulta de solución para su ejemplo para MS SQL Server 2012 (y SQL Server 2014):
ORDER BY CASE WHEN Next_Contact_Date IS NULL THEN 1 ELSE 0 END, Next_Contact_Date;
Código equivalente con sintaxis IIF:
fuente
Si su SQL no admite
NULLS FIRST
oNULLS LAST
, la forma más sencilla de hacer esto es usar lavalue IS NULL
expresión:para poner los nulos al final (
NULLS LAST
) opara poner los nulos al frente. Esto no requiere conocer el tipo de columna y es más fácil de leer que la
CASE
expresión.EDITAR: Por desgracia, aunque esto funciona en otras implementaciones de SQL como PostgreSQL y MySQL, no funciona en MS SQL Server. No tenía un servidor SQL para probar y confié en la documentación y las pruebas de Microsoft con otras implementaciones de SQL. Según Microsoft,
value IS NULL
es una expresión que debería ser utilizable como cualquier otra expresión. YORDER BY
se supone que toma expresiones como cualquier otra declaración que toma una expresión. Pero en realidad no funciona.Por tanto, la mejor solución para SQL Server parece ser la
CASE
expresión.fuente
fuente
Next_Contact_Date
es nuloExplicit conversion from data type date to bigint is not allowed.
Un poco tarde, pero tal vez alguien lo encuentre útil.
Para mí, ISNULL estaba fuera de discusión debido al escaneo de la tabla. UNION ALL necesitaría que repitiera una consulta compleja, y debido a que seleccioné solo el TOP X, no habría sido muy eficiente.
Si puede cambiar el diseño de la mesa, puede:
Agregue otro campo, solo para ordenar, como Next_Contact_Date_Sort.
Cree un disparador que llene ese campo con un valor grande (o pequeño), según lo que necesite:
CREATE TRIGGER FILL_SORTABLE_DATE ON YOUR_TABLE AFTER INSERT,UPDATE AS BEGIN SET NOCOUNT ON; IF (update(Next_Contact_Date)) BEGIN UPDATE YOUR_TABLE SET Next_Contact_Date_Sort=IIF(YOUR_TABLE.Next_Contact_Date IS NULL, 99/99/9999, YOUR_TABLE.Next_Contact_Date_Sort) FROM inserted i WHERE YOUR_TABLE.key1=i.key1 AND YOUR_TABLE.key2=i.key2 END END
fuente
Use desc y multiplique por -1 si es necesario. Ejemplo de orden int ascendente con nulos al final:
select * from (select null v union all select 1 v union all select 2 v) t order by -t.v desc
fuente
Sé que esto es viejo pero esto es lo que funcionó para mí
fuente