MySQL: récupère MAX ou PLUS de plusieurs colonnes, mais avec des champs NULL

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