2009-09-30 12 views
213

J'ai une table SQL avec un champ datetime. Le champ en question peut être nul. J'ai une requête et je veux que les résultats soient triés de manière ascendante par le champ datetime, mais je veux des lignes où le champ datetime est nul à la fin de la liste, pas au début.SQL comment faire des valeurs nulles viennent en dernier lors du tri ascendant

Existe-t-il un moyen simple d'accomplir cela?

+5

double exact de http://stackoverflow.com/questions/151195/possible-to-use-sql-to-sort-by-date-but-put-null-dates-at-the-back -des-résultats –

+0

Voir aussi http: // stackoverflow.com/questions/15121093/django-ajout-nulls-dernier-à-requête/35494930 # 35494930 et https://code.djangoproject.com/ticket/13312 – Risadinha

Répondre

308
select MyDate 
from MyTable 
order by case when MyDate is null then 1 else 0 end, MyDate 
+1

Notez toutefois que si vous placez un index sur la colonne de tri pour améliorer les performances (*), cette méthode compliquera quelque peu le plan de requête et perdra une grande partie des avantages en termes de performances. * - les index fournissaient les données pré-triées, évitant ainsi un tri par exécution de requête. Il est conseillé de filtrer les enregistrements NULL si possible pour éviter complètement ce problème. – redcalx

+1

Belle réponse également donnée ici avec tous les avantages possibles et les inconvénients http://nickstips.wordpress.com/2010/09/30/sql-order-by-with-null-values-last/ – sudhAnsu63

+17

'order by case quand MyDate est null alors 1 autre 0 end' est une façon très longue de dire 'ORDER BY MyDate IS NULL' – Martin

13
order by coalesce(date-time-field,large date in future) 
+9

Bien que cela fonctionne généralement, il convient de noter que cette réponse a un quelques problèmes: une date importante à l'avenir peut entrer en collision avec ou être inférieure à des données réelles, ce qui entraîne un tri imparfait. En outre, il s'agit d'une solution «nombre magique» qui n'est pas auto-documentée. – RedFilter

+0

Cela s'avère être une excellente alternative à la réponse @RedFilter lorsque vous avez besoin de comparer la colonne en question à une autre colonne de date. Je l'utilise pour la liste d'ancienneté syndicale. Si l'employé a une date qualifiée (qui est nullable), cette date fait apparaître une bulle vers le haut, sinon utilisez HireDate. En utilisant ORDER BY ISNULL (QualifiedDate, '1-1-2099'), HireDate, LastName, etc. rend la date qualifiée pas en conflit avec la date de HiredDate et la liste de senirity correcte est produite. –

11

Vous pouvez utiliser la fonction intégrée pour vérifier nulle ou non nulle, comme ci-dessous. Je l'ai testé et ça fonctionne bien.

select MyDate from MyTable order by ISNULL(MyDate,1) DESC, MyDate ASC;

+0

Pour les dates de travail avec mssql, j'ai trouvé utile de mettre une date lointaine dans la fonction ISNULL, c'est-à-dire ISNULL (MyDate, '2100-01-01') –

+0

Dans MySQL, il est dit que je passe trop de paramètres. J'ai obtenu ceci pour analyser en faisant 'ISNULL (MyDate) DESC, MyDate ASC', mais il n'a pas trié dans le bon ordre. – AdmiralAdama

127

(« un peu » en retard, mais cela n'a pas été mentionné du tout)

Vous n'avez pas spécifié votre SGBD.

SQL standard (et la plupart des SGBD modernes comme Oracle, PostgreSQL, DB2, Firebird, Apache Derby, HSQLDB et H2) vous pouvez spécifier NULLS LAST ou NULLS FIRST:

Utilisez NULLS LAST pour les trier à la fin:

select * 
from some_table 
order by some_column DESC NULLS LAST 
+12

AFAIK 'NULLS FIRST' et' NULLS LAST' ont été ajoutés dans SQL: 2003 mais il n'y a pas d'implémentation standard disponible dans les différents DMBS. Selon le moteur de base de données, utilisez 'ORDER BY expr une_colonne DESC NULLS LAST' (Oracle),' ORDER BY ISNULL (une_colonne, 1), une_colonne ASC' (MSSQL) ou 'ORDER BY ISNULL (une_colonne), une_colonne ASC' (MySQL avec une implémentation ISNULL() différente). – SaschaM78

+1

@ SaschaM78: le tri par défaut des NULL dépend du SGBD. Certains les trient à la fin, d'autres au début. Certains ne se soucient pas de 'ASC' /' DESC' avec des valeurs nulles. La seule façon d'assurer cela est d'utiliser 'NULL FIRST/LAST' ** si ** le SGBD le supporte. À ce * documents * ce que vous avez l'intention. L'utilisation de 'isnull()' ou d'autres fonctions est une solution de contournement pour le support manquant de 'NULLS FIRST/LAST' (supporté par Oracle, PostgreSQL, DB2, Firebird, Apache Derby, HSQLDB et H2) –

+0

Vous avez parfaitement raison , Je voulais juste ajouter le fait qu'il y a quelques SGBD autour qui ne suivent pas (encore) la norme ou ont leurs spécialités comme Oracle nécessitant le mot-clé 'expr' lors de l'utilisation de NULLS FIRST/LAST. Et merci pour les nulls affichés en premier/dernier variant du type de base de données au type, je ne le savais pas! – SaschaM78

26

Je viens aussi trébuché à travers cela et ce qui suit semble faire l'affaire pour moi, sur MySQL et PostgreSQL:

ORDER BY date IS NULL, date DESC 

trouvé à https://stackoverflow.com/a/7055259/496209

+0

Cela semble prometteur, mais malheureusement, je l'ai essayé et 'IS NULL' et' IS NOT NULL' ne fonctionnait pas dans ma base de données MySQL. – AdmiralAdama

3

Merci RedFilter d'avoir fourni une excellente solution au problème d'encombrement du tri temporel du champ datetime. J'utilise la base de données SQL Server pour mon projet.

La modification de la valeur null datetime à '1' permet de résoudre le problème de tri de la colonne de type datetime datatype. Cependant, si nous avons une colonne avec un type de données autre que datetime, elle ne peut pas gérer.

Pour gérer un tri de colonnes varchar, j'ai essayé d'utiliser 'ZZZZZZZ' car je savais que la colonne n'avait pas de valeurs commençant par 'Z'. Cela a fonctionné comme prévu. Sur les mêmes lignes, j'ai utilisé les valeurs maximales +1 pour int et d'autres types de données pour obtenir le tri comme prévu. Cela m'a aussi donné les résultats comme requis.

Cependant, il serait toujours idéal pour obtenir quelque chose plus facile dans le moteur de base de données lui-même qui pourrait faire quelque chose comme: Comme mentionné dans la réponse fournie par a_horse_with_no_name

Order by Col1 Asc Nulls Last, Col2 Asc Nulls First 

.

1
order by -cast([nativeDateModify] as bigint) desc 
1

Solution en utilisant le "cas" est universel, mais ne pas utiliser les index.

order by case when MyDate is null then 1 else 0 end, MyDate 

Dans mon cas, j'avais besoin de performances.

SELECT smoneCol1,someCol2 
FROM someSch.someTab 
WHERE someCol2 = 2101 and (someCol1 IS NULL) 
    UNION 
SELECT smoneCol1,someCol2 
FROM someSch.someTab 
WHERE someCol2 = 2101 and ( someCol1 IS NOT NULL) 
+1

Si vous êtes intéressé par les performances, vous devriez utiliser 'UNION ALL'. – RedFilter

6

Si votre moteur le permet ORDER BY x IS NULL, x ou ORDER BY x NULLS LAST utiliser cela. Mais si elle ne peut aider ces:

Si vous triez par un type numérique que vous pouvez faire ceci: (Empruntant le schéma de another answer.)

SELECT *   
FROM Employees 
ORDER BY ISNULL(DepartmentId*0,1), DepartmentId; 

result showing sorted by DepartmentId with nulls last

Tout non -null number devient 0, et null devient 1, ce qui trie les nulls en dernier.

Vous pouvez aussi le faire pour les chaînes:

SELECT * 
FROM Employees 
ORDER BY ISNULL(LEFT(LastName,0),'a'), LastName 

result showing sorted by LastName with nulls last

Parce que 'a'>''.

Cela fonctionne même avec des dates en forçant à un int nullable et en utilisant la méthode de ints ci-dessus:

SELECT * 
FROM Employees 
ORDER BY ISNULL(CONVERT(INT, HireDate)*0, 1), HireDate 

(Lets prétendre que le schéma a HireDate.)

Ces méthodes évitent la question d'avoir trouver ou gérer une valeur "maximum" de chaque type ou corriger des requêtes si le type de données (et le maximum) change (les deux problèmes que subissent les autres solutions ISNULL). De plus, ils sont beaucoup plus courts qu'un CAS.

2

Lorsque votre colonne de commande est numérique (comme un rang), vous pouvez la multiplier par -1, puis la trier par ordre décroissant. Il conservera l'ordre que vous attendez mais mettra NULL en dernier.

select * 
from table 
order by -rank desc 
+0

Étais sur le point de commenter cela. L'a appris de https://stackoverflow.com/a/8174026/1193304 et c'est génial – Chris

Questions connexes