MySQL:得到几列的MAX或GREATEST,但是有NULL字段

Iva*_*van 55 mysql null max

我试图在每个记录(MySQL)的三个不同字段中选择最大日期所以,在每一行中,我有date1,date2和date3:date1总是填充,date2和date3可以是NULL或空GREATEST语句是简单而简洁但对NULL字段没有影响,所以这不能很好地工作:

SELECT id, GREATEST(date1, date2, date3) as datemax FROM mytable
Run Code Online (Sandbox Code Playgroud)

我尝试了更复杂的解决方案,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

这里的问题相同:返回正确的记录时,NULL值是一个很大的问题

拜托,你有解决方案吗?提前致谢....

Mat*_*dge 94

使用 COALESCE

SELECT id, 
   GREATEST(date1, 
     COALESCE(date2, 0),
     COALESCE(date3, 0)) as datemax 
FROM mytable
Run Code Online (Sandbox Code Playgroud)

更新:以前使用的这个答案IFNULL确实有效,但正如Mike Chamberlain在评论中指出的那样,COALESCE实际上是首选的方法.

  • 澄清COALESCE正在做什么(因为我不知道它直接理解它,所以认为它可能有助于其他人得到解释).COALESCE返回第一个非Null值,因此通过传递日期和0然后如果日期为null,则COALESCE(date,0)的输出将为0,并且您将在日期和0之间取得最大值,从而得到在你的约会.我不明白为什么它起初有效,但现在我做了.进一步阅读https://www.w3resource.com/mysql/comparision-functions-and-operators/coalesce-function.php (2认同)
  • @MattDodge-您提到“ Mike Chamberlain”的评论,该评论似乎不再存在。您能解释为什么`COALESCE()`比IFNULL()`更可取吗?我认为后者会更有表现。 (2认同)
  • @billynoah好已经有7年多了,所以我的记忆有点模糊哈哈,但我相信有些文档明确建议使用COALESCE,因为它是通用SQL规范或类似内容的一部分。我对性能的影响尚不清楚。 (2认同)

ype*_*eᵀᴹ 31

如果date1永远不可能NULL,那么结果永远不应该是NULL,对吧?然后,如果你愿意,你可以利用这一点,NULL日期计算时将不计(或更改1000-01-019999-12-31,如果你想空值计算为"地老天荒"):

GREATEST( date1
        , COALESCE(date2, '1000-01-01')
        , COALESCE(date3, '1000-01-01')
        ) AS datemax
Run Code Online (Sandbox Code Playgroud)


san*_*zti 6

但是,如果所有日期碰巧都为空怎么办?您仍然希望将 null 作为输出,对吗?那么你需要这个

select nullif(greatest(coalesce(<DATEA>, from_unixtime(0)), coalesce(<DATEB>, from_unixtime(0))), from_unixtime(0));
Run Code Online (Sandbox Code Playgroud)

现在,如果两者都为 null,则得到 null,如果其中之一不为 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 ;
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它

select cp_greatest_date(current_timestamp, null);
-- output is 2017-05-05 20:22:45
Run Code Online (Sandbox Code Playgroud)


hkf*_*hkf 5

COALESCE您使用它们之前的日期列GREATEST.

你处理它们的方式取决于你想要处理的方式NULL......高或低?