J'essaie de commander par date. Je veux les dates les plus récentes à venir en premier. C'est assez facile, mais de nombreux enregistrements sont nuls et viennent avant ceux ayant une date.
J'ai essayé quelques choses sans succès:
ORDER BY ISNULL(Next_Contact_Date, 0)
ORDER BY ISNULL(Next_Contact_Date, 999999999)
ORDER BY coalesce(Next_Contact_Date, 99/99/9999)
Comment puis-je commander par date et faire en sorte que les valeurs NULL arrivent en dernier? Le type de données est smalldatetime
.
smalldatetime
va jusqu'au 6 juin 2079 pour que vous puissiez utiliser
ORDER BY ISNULL(Next_Contact_Date, '2079-06-05T23:59:00')
Si aucun enregistrement légitime n'aura cette date.
S'il ne s'agit pas d'une hypothèse, il est préférable de trier sur deux colonnes une option plus robuste.
ORDER BY CASE WHEN Next_Contact_Date IS NULL THEN 1 ELSE 0 END, Next_Contact_Date
Les deux suggestions ci-dessus ne permettent pas d'utiliser un index pour éviter un tri et donner des plans similaires.
Une autre possibilité si un tel index existe est
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
Selon Itzik Ben-Gan, auteur de Principes de base de T-SQL pour MS SQL Server 2012, "Par défaut, SQL Server trieNULLmarques avant non -NULLvaleurs. Pour obtenirNULLmarques à trier en dernier, vous pouvez utiliser une expressionCASEqui retourne 1 lorsque "Next_Contact_Datecolumn estNULL, "et 0 s'il ne l'est pasNULL. Non -NULLLes marques récupèrent 0 de l’expression et sont donc triées avantNULLmarques (qui obtiennent 1). Cette expressionCASEest utilisée comme la première colonne de tri. " La colonneNext_Contact_Date"doit être spécifiée comme deuxième colonne de tri. De cette manière, les marques non -NULLsont correctement triées entre elles." Voici la requête de solution pour votre exemple pour MS SQL Server 2012 (et SQL Server 2014):
ORDER BY
CASE
WHEN Next_Contact_Date IS NULL THEN 1
ELSE 0
END, Next_Contact_Date;
Code équivalent utilisant la syntaxe IIF:
ORDER BY
IIF(Next_Contact_Date IS NULL, 1, 0),
Next_Contact_Date;
Un peu tard, mais peut-être que quelqu'un trouvera cela utile.
Pour moi, ISNULL était hors de question en raison de l'analyse de la table. UNION ALL aurait besoin de moi pour répéter une requête complexe, et comme je n'avais sélectionné que le TOP X, cela n'aurait pas été très efficace.
Si vous pouvez modifier la conception de la table, vous pouvez:
Ajoutez un autre champ, uniquement pour le tri, tel que Next_Contact_Date_Sort.
Créez un déclencheur qui remplit ce champ avec une grande (ou petite) valeur, selon vos besoins:
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
order by -cast([Next_Contact_Date] as bigint) desc
Si votre code SQL ne prend pas en charge NULLS FIRST
ou NULLS LAST
, le moyen le plus simple consiste à utiliser l'expression value IS NULL
:
ORDER BY Next_Contact_Date IS NULL, Next_Contact_Date
mettre les valeurs nuls à la fin (NULLS LAST
) ou
ORDER BY Next_Contact_Date IS NOT NULL, Next_Contact_Date
mettre les nuls à l'avant. Cela n'exige pas de connaître le type de la colonne et est plus facile à lire que l'expression CASE
.
EDIT: Hélas, bien que cela fonctionne dans d'autres implémentations SQL telles que PostgreSQL et MySQL, cela ne fonctionne pas dans MS SQL Server. Je n'avais pas de serveur SQL sur lequel tester et je m'appuyais sur la documentation de Microsoft et sur des tests avec d'autres implémentations SQL. Selon Microsoft, value IS NULL
est une expression qui devrait être utilisable comme toute autre expression. Et ORDER BY
est supposé prendre des expressions comme toute autre déclaration qui prend une expression. Mais ça ne marche pas vraiment.
La meilleure solution pour SQL Server semble donc être l'expression CASE
.
Utilisez desc et multipliez par -1 si nécessaire. Exemple de classement int croissant avec les valeurs NULL en dernier:
select *
from
(select null v union all select 1 v union all select 2 v) t
order by -t.v desc
Je sais que c'est vieux mais c'est ce qui a fonctionné pour moi
Order by Isnull(Date,'12/31/9999')