MySQL: получить MAX или GREATEST из нескольких столбцов, но с полями NULL - PullRequest
49 голосов
/ 23 марта 2012

Я пытаюсь выбрать максимальную дату в трех разных полях в каждой записи (MySQL) Итак, в каждой строке у меня есть date1, date2 и date3: date1 всегда заполнен, date2 и date3 могут быть NULL или пустыми Оператор GREATEST прост и лаконичен, но не влияет на поля NULL, поэтому он не работает должным образом:

SELECT id, GREATEST(date1, date2, date3) as datemax FROM mytable

Я пробовал и более сложные решения, подобные этому:

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

Та же проблема здесь: значения NULL - БОЛЬШАЯ проблема при возврате правильных записей

Пожалуйста, у вас есть решение? Заранее спасибо ....

Ответы [ 4 ]

89 голосов
/ 23 марта 2012

Использование COALESCE

SELECT id, 
   GREATEST(date1, 
     COALESCE(date2, 0),
     COALESCE(date3, 0)) as datemax 
FROM mytable

Обновление: Этот ответ ранее использовал IFNULL, который работает, но, как отметил Майк Чемберлен в комментариях, COALESCE на самом деле является предпочтительным методом.

30 голосов
/ 23 марта 2012

Если date1 никогда не может быть NULL, то результат никогда не должен быть NULL, верно? Тогда вы можете использовать это, если хотите, чтобы NULL даты не учитывались в расчетах (или измените 1000-01-01 на 9999-12-31, если хотите, чтобы значения Null считались как «конец времени»):

GREATEST( date1
        , COALESCE(date2, '1000-01-01')
        , COALESCE(date3, '1000-01-01')
        ) AS datemax
5 голосов
/ 23 марта 2012

COALESCE ваши столбцы даты, прежде чем использовать их в GREATEST.

То, как вы их обработаете, будет зависеть от того, как вы хотите иметь дело с NULL .. как высоким, так и низким?

0 голосов
/ 06 мая 2017

buuut, если все даты оказываются нулевыми?Вы все еще хотите иметь нулевое значение в качестве вывода, верно?тогда вам нужно это

select nullif(greatest(coalesce(<DATEA>, from_unixtime(0)), coalesce(<DATEB>, from_unixtime(0))), from_unixtime(0));

Теперь, если оба равны нулю, вы получаете ноль, если один из них не равен нулю, и оба они не равны нулю, вы получаете наибольшее значение.

Этоэто безумие, особенно если вы будете использовать его несколько раз, для этого вам может потребоваться создать его как функцию, например:

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 ;

Затем вы можете использовать ее вот так

select cp_greatest_date(current_timestamp, null);
-- output is 2017-05-05 20:22:45
...