J’essaie de sélectionner la date max dans trois champs différents dans chaque enregistrement (MySQL) Donc, dans chaque ligne, j’ai date1, date2 et date3: date1 est toujours rempli, date2 et date3 peuvent être NULL ou vide L’instruction GREATEST est simple et concis mais sans effets sur les champs NULL, cela ne fonctionne pas bien:
SELECT id, GREATEST(date1, date2, date3) as datemax FROM mytable
J’ai aussi essayé des solutions plus complexes comme celle-ci:
SELECT CASE WHEN date1 >= date2 AND date1 >= date3 THEN date1 WHEN date2 >= date1 AND date2 >= date3 THEN date2 WHEN date3 >= date1 AND date3 >= date2 THEN date3 ELSE date1 END AS MostRecentDate
Même problème ici: les valeurs NULL sont un grand problème pour retourner les enregistrements corrects
S’il vous plaît, avez-vous une solution? Merci d’avance….
Utilisez COALESCE
SELECT id, GREATEST(date1, COALESCE(date2, 0), COALESCE(date3, 0)) as datemax FROM mytable
Mise à jour: Cette réponse utilisait précédemment IFNULL
qui fonctionne, mais comme Mike Chamberlain l’a souligné dans les commentaires, COALESCE
est en fait la méthode préférée.
Si date1
ne peut jamais être NULL
, le résultat ne devrait jamais être NULL
, non? Vous pouvez ensuite l’utiliser si vous souhaitez que les dates NULL
ne soient pas sockets en compte dans les calculs (ou modifiez le 1000-01-01
à 9999-12-31
, si vous souhaitez que Nulls soit considéré comme la “fin du temps”):
GREATEST( date1 , COALESCE(date2, '1000-01-01') , COALESCE(date3, '1000-01-01') ) AS datemax
COALESCE
vos colonnes de date avant de les utiliser dans GREATEST
.
La façon dont vous les manipulerez dépendra de la manière dont vous voulez gérer NULL
.. haute ou basse?
buuut, si toutes les dates sont nulles? vous voulez toujours avoir null comme sortie, non? alors vous avez besoin de cela
select nullif(greatest(coalesce(, from_unixtime(0)), coalesce(, from_unixtime(0))), from_unixtime(0));
Maintenant, si les deux sont null, vous obtenez null, si l’un d’eux n’est pas nul, les deux ne sont pas null, vous obtenez le meilleur.
C’est fou, surtout si vous l’utilisez plusieurs fois, pour cela, vous voudrez peut-être le créer comme une fonction, comme ceci:
delimiter // drop function if exists cp_greatest_date// create function cp_greatest_date ( dateA timestamp, dateB timestamp ) returns timestamp deterministic reads sql data begin # if both are null you get null, if one of them is not null of both of them are not null, you get the greatest set @output = nullif(greatest(coalesce(dateA, from_unixtime(0)), coalesce(dateB, from_unixtime(0))), from_unixtime(0)); # santiago arizti return @output; end // delimiter ;
Ensuite, vous pouvez l’utiliser comme ça
select cp_greatest_date(current_timestamp, null); -- output is 2017-05-05 20:22:45