Подтвердить что ты не робот

MySQL: получите MAX или GREATEST из нескольких столбцов, но с полями NULL

Я пытаюсь выбрать максимальную дату в трех разных полях в каждой записи (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 - БОЛЬШАЯ проблема при возврате правильных записей

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

4b9b3361

Ответ 1

Используйте COALESCE

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

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

Ответ 2

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

GREATEST( date1
        , COALESCE(date2, '1000-01-01')
        , COALESCE(date3, '1000-01-01')
        ) AS datemax

Ответ 3

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

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

Ответ 4

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

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

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

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

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