GREATEST Skips NULL on PostgreSQL and Returns NULL on MySQL
GREATEST(sale_price, list_price) picks the larger of two prices. When one of them is NULL, PostgreSQL still picks the other price, and no other engine does.
GREATEST(1, NULL) is 1 on PostgreSQL and NULL on MySQL and MariaDB. SQLite has the same idea under the names MAX(a, b) and MIN(a, b) with two or more arguments; they return NULL when any argument is NULL, and the other engines read MAX and MIN as aggregates.

What Each Engine Answered
On a table made with
CREATE TABLE t (id INTEGER PRIMARY KEY, a INTEGER, b INTEGER);
INSERT INTO t VALUES (1, 1, NULL), (2, NULL, 5);
the example
SELECT GREATEST(a, b) FROM t ORDER BY id;
gave these answers:
| Engine | Answer |
|---|---|
| SQLite 3.45.1 | error: no such function: GREATEST |
| PostgreSQL 16.15 | 1; 5 |
| MySQL 8.0.46 | NULL; NULL |
| MariaDB 10.11.14 | NULL; NULL |
What to Write Instead
This form answers the same on every engine:
SELECT CASE WHEN a IS NULL THEN b WHEN b IS NULL OR a >= b THEN a ELSE b END FROM t ORDER BY id;
| Engine | Answer |
|---|---|
| SQLite 3.45.1 | 1; 5 |
| PostgreSQL 16.15 | 1; 5 |
| MySQL 8.0.46 | 1; 5 |
| MariaDB 10.11.14 | 1; 5 |
Write it out with CASE and say what NULL should do. CASE WHEN a IS NULL THEN b WHEN b IS NULL OR a >= b THEN a ELSE b END skips NULL, as PostgreSQL’s GREATEST does, on all four engines. A plain CASE WHEN a >= b THEN a ELSE b END answers b whenever the comparison meets a NULL, so it gives 5 for (NULL, 5) and NULL for (1, NULL).
What BareSQL Portable Reports
Saved as example.sql, the example gets this from baresql lint --all:
$ baresql lint --all example.sql
example.sql:3:8: error: GREATEST and LEAST are missing on SQLite, skip NULL on PostgreSQL and return NULL on MySQL and MariaDB. [greatest-least]
GREATEST(a, b)
Write it out with CASE and say what NULL should do. CASE WHEN a IS NULL THEN b WHEN b IS NULL OR a >= b THEN a ELSE b END skips NULL, as PostgreSQL's GREATEST does, on all four engines. A plain CASE WHEN a >= b THEN a ELSE b END answers b whenever the comparison meets a NULL, so it gives 5 for (NULL, 5) and NULL for (1, NULL).
1 problem: 1 error.
baresql rules greatest-least prints the same answers in the terminal, and the BareSQL Portable page lists every difference BareSQL knows.