web-dev-qa-db-ja.com

MySQL:複数の列のMAXまたはGREATESTを取得しますが、フィールドはNULLです

私は各レコードの3つの異なるフィールドで最大日付を選択しようとしています(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値は正しいレコードを返す際の大きな問題です

解決策はありますか?前もって感謝します....

50
Ivan

COALESCEを使用

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

更新:この回答では、以前はIFNULLを使用していましたが、Mike Chamberlainがコメントで指摘したように、COALESCEが実際に推奨される方法です。

91
Matt Dodge

date1NULLにならない場合、結果はNULLにならないはずですよね?その後、NULL日付を計算でカウントしない場合はこれを使用できます(またはNullを「終了時間」としてカウントする場合は1000-01-019999-12-31に変更します"):

GREATEST( date1
        , COALESCE(date2, '1000-01-01')
        , COALESCE(date3, '1000-01-01')
        ) AS datemax
30
ypercubeᵀᴹ

COALESCEで使用する前に、日付列をGREATESTにしてください。

それらを処理する方法は、NULL ..をどのように処理したいかによって異なります。

5
hkf

buuut、すべての日付がnullになったら?まだ出力としてnullが必要ですか?あなたはこれが必要です

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

ここで、両方がnullの場合、nullを取得し、そのうちの1つが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
2
santiago arizti