web-dev-qa-db-fra.com

SQL comment faire en sorte que les valeurs nulles viennent en dernier lors du tri croissant

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 par ordre croissant par le champ datetime. Cependant, je veux des lignes où le champ datetime est nul à la fin de la liste, pas au début.

Y a-t-il un moyen simple d'y parvenir?

271
David Božjak
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate
364
RedFilter

(Un "peu" en retard, mais cela n'a pas été mentionné du tout)

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

En SQL standard (et dans les SGBD les plus 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 jusqu'à la fin:

select *
from some_table
order by some_column DESC NULLS LAST
150

Je suis aussi tombé sur ça et ce qui suit semble faire l'affaire pour moi, sur MySQL et PostgreSQL:

ORDER BY date IS NULL, date DESC

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

32
Luksurious
order by coalesce(date-time-field,large date in future)
14
Gratzy

Vous pouvez utiliser la fonction intégrée pour rechercher la valeur null ou non null, comme indiqué ci-dessous. Je le teste et tout fonctionne bien.

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

13

Si votre moteur autorise ORDER BY x IS NULL, x ou ORDER BY x NULLS LAST, utilisez-le. Mais si cela ne fonctionne pas, cela pourrait aider:

Si vous triez par type numérique, vous pouvez procéder comme suit: (Emprunter le schéma de autre réponse .)

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

result showing sorted by DepartmentId with nulls last

Tout nombre non nul devient 0, et les nuls deviennent 1, ce qui trie les nuls en dernier.

Vous pouvez également 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 les dates en contraignant à un int nullable et en utilisant la méthode pour les entiers ci-dessus:

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

(Supposons que le schéma a HireDate.)

Ces méthodes évitent de devoir définir ou gérer une valeur "maximale" de chaque type ou de résoudre les requêtes si le type de données (et le maximum) change (les deux problèmes que les autres solutions ISNULL subissent). De plus, ils sont beaucoup plus courts qu'un CASE.

11
infogulch

Lorsque votre colonne d'ordre est numérique (comme un rang), vous pouvez la multiplier par -1 puis par ordre décroissant. Il gardera l'ordre dans lequel vous êtes en train d'exécuter mais mettez NULL en dernier.

select *
from table
order by -rank desc
6
Luizgrs
SELECT *          
FROM Employees
ORDER BY ISNULL(DepartmentId, 99999);

Voir cet article de blog .

4
user3923117

Dans Oracle, vous pouvez utiliser NULLS FIRST ou NULLS LAST: spécifie que les valeurs NULL doivent être renvoyées avant/après les valeurs non NULL:

ORDER BY { column-Name | [ ASC | DESC ] | [ NULLS FIRST | NULLS LAST ] }

Par exemple:

ORDER BY date DESC NULLS LAST

Réf.: http://docs.Oracle.com/javadb/10.8.3.0/ref/rrefsqlj13658.html

3
Joaquinglezsantos

Merci à RedFilter d’avoir fourni une excellente solution au problème de tri du champ date/heure nullable.

J'utilise la base de données SQL Server pour mon projet.

Le fait de modifier la valeur NULL datetime sur "1" résout le problème du tri de la colonne datatype datetime. Cependant, si nous avons une colonne avec un type de données autre que datetime, elle ne pourra pas être traitée.

Pour gérer un tri de colonne varchar, j'ai essayé d'utiliser 'ZZZZZZZ' car je savais que la colonne n'avait pas de valeur 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 souhaité. Cela m'a également donné les résultats requis.

Cependant, il serait toujours idéal d’obtenir quelque chose de plus simple dans le moteur de base de données lui-même, qui pourrait faire quelque chose comme:

Order by Col1 Asc Nulls Last, Col2 Asc Nulls First 

Comme mentionné dans la réponse fournie par a_horse_with_no_name.

3
Kasim Husaini
order by -cast([nativeDateModify] as bigint) desc
1
paparazzo

Si vous utilisez MariaDB, ils mentionnent les éléments suivants dans la documentation sur les valeurs NULL .

Commande

Lorsque vous commandez selon un champ pouvant contenir des valeurs NULL, tous les NULL sont considérés comme ayant la valeur la plus basse. Ainsi, l'ordre dans l'ordre DESC affichera les valeurs NULL en dernier. Pour forcer les valeurs NULL à être considérées comme les valeurs les plus élevées, on peut ajouter une autre colonne ayant une valeur plus élevée lorsque le champ principal est NULL. Exemple:

SELECT col1 FROM tab ORDER BY ISNULL(col1), col1;

Ordre décroissant, avec NULL en premier:

SELECT col1 FROM tab ORDER BY IF(col1 IS NULL, 0, 1), col1 DESC;

Toutes les valeurs NULL sont également considérées comme équivalentes aux fins des clauses DISTINCT et GROUP BY.

Ce qui précède montre deux manières de classer par valeurs NULL. Vous pouvez également les combiner avec les mots-clés ASC et DESC. Par exemple, l’autre moyen d’obtenir les valeurs NULL d’abord serait:

SELECT col1 FROM tab ORDER BY ISNULL(col1) DESC, col1;
--                                         ^^^^
1
3limin4t0r

La solution utilisant le "cas" est universelle, mais n'utilisez pas les index.

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

Dans mon cas, j'avais besoin de performance.

 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
Adam111p

UTILISER la fonction NVL

  select * from MyTable order by NVL(MyDate, to_date('1-1-1','DD-MM-YYYY'))

Voici l'alternative de NVL dans le plus célèbre SGBD

0
Charmi