Comparisons (=, <> or !=, <, <=, >, >=) return 1, 0 or NULL; <=> is the NULL-safe equal, and IS [NOT] TRUE, FALSE or UNKNOWN tests a truth value. x BETWEEN a AND b means x >= a AND x <= b, IN tests a list, and row constructors compare left to right, the way a composite index sorts. The logical operators are AND, OR, NOT and XOR.
SELECT id, rating, body IS NULL AS no_text, rating <=> 4 AS is4,
rating BETWEEN 3 AND 4 AS mid, product_id IN (1, 6) AS in_list,
(product_id, rating) > (2, 3) AS row_gt, (rating > 3) XOR (body IS NULL) AS one_of,
customer_id NOT IN (3, NULL) AS not_in_null
FROM reviews WHERE customer_id IN (1, 2);Output
+----+--------+---------+-----+-----+---------+--------+--------+-------------+ | id | rating | no_text | is4 | mid | in_list | row_gt | one_of | not_in_null | +----+--------+---------+-----+-----+---------+--------+--------+-------------+ | 1 | 5 | 0 | 0 | 0 | 1 | 0 | 1 | NULL | | 5 | 4 | 1 | 1 | 1 | 1 | 1 | 0 | NULL | | 2 | 4 | 0 | 1 | 1 | 0 | 1 | 1 | NULL | | 3 | 3 | 0 | 0 | 1 | 0 | 1 | 0 | NULL | +----+--------+---------+-----+-----+---------+--------+--------+-------------+
No row belongs to customer 3, yet NOT IN (3, NULL) is NULL for all of them, so a WHERE with it keeps nothing: the classic NOT IN (SELECT ...) bug (IN, ANY, ALL, and EXISTS). Under utf8mb4_0900_ai_ci, 'abc' = 'ABC' is 1, but, because the collation is NO PAD, 'abc' = 'abc ' is 0. &&, || and ! raise deprecation warning 1287; write AND, OR and NOT.