select c1, c2,
case when c1 > c2 then c1 else coalesce(c2,c1) end as max
from twocol;
+------+------+------+
| c1 | c2 | max |
+------+------+------+
| NULL | NULL | NULL |
| NULL | 2 | 2 |
| 1 | NULL | 1 |
| 1 | 2 | 2 |
| NULL | NULL | NULL |
| 2 | NULL | 2 |
| NULL | 1 | 1 |
| 2 | 1 | 2 |
+------+------+------+
Почему это работает? если ни один из операндов не является нулевым, то мы получаем «нормальное» сравнение: ветвь then при c1> c2, ветвь else при c1 <= c2. </p>
В ветке "else" мы называем coalesce, но так как ее первый аргумент - ненулевое c2, мы возвращаем c2.
.
Но если любой операнд имеет значение null, тест c1 > c2
оценивается как false, и мы возвращаем coalesce( c2, c1 )
.
Если нулевым операндом был c1, мы получаем c2, чего мы и хотим, потому что мы (для этого вопроса) называем null «меньше» любого ненулевого значения.
Если нулевым операндом был c2, мы получаем c1. Это нормально, потому что c1 либо не нуль, и, таким образом (для этого вопроса) "больше", чем ноль c2, или ...
Если оба операнда были нулевыми, мы получаем c1, но не имеет значения, какой получим, поскольку оба равны нулю.
Дополнительным преимуществом является то, что эта идиома работает для любых типов, для которых operator >
работает, без дальнейших размышлений или подробностей.