Description:
The following ORDER BY for the utf8mb4_0900_ai_ci column returns in correct order.
mysql> SELECT c1, SUBSTR(c1, 1) AS dummy FROM t1 ORDER BY dummy ASC;
+------+-------+
| c1 | dummy |
+------+-------+
| | |
| NULL | NULL |
| | |
| NULL | NULL |
+------+-------+
4 rows in set (0.00 sec)
The NULL values should be presented first as same as the result of ORDER BY c1.
> > When doing an ORDER BY, NULL values are presented first if you do ORDER BY ... ASC and last if you do ORDER BY ... DESC.
> https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html
mysql> SELECT c1, SUBSTR(c1, 1) AS dummy FROM t1 ORDER BY c1 ASC;
+------+-------+
| c1 | dummy |
+------+-------+
| NULL | NULL |
| NULL | NULL |
| | |
| | |
+------+-------+
4 rows in set (0.00 sec)
Other string functions also have same behavior.
e.g.
SELECT c1, CONCAT(c1, '') AS dummy FROM t1 ORDER BY dummy ASC;
SELECT c1, LTRIM(c1) AS dummy FROM t1 ORDER BY dummy ASC;
And ORDER BY with DESC also does not work.
mysql> SELECT c1, SUBSTR(c1, 1) AS dummy FROM t1 ORDER BY dummy DESC;
+------+-------+
| c1 | dummy |
+------+-------+
| | |
| NULL | NULL |
| | |
| NULL | NULL |
+------+-------+
How to repeat:
mysql> CREATE TABLE t1 (c1 char(100) COLLATE 'utf8mb4_0900_ai_ci');
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO t1 VALUES (''), (NULL), (''), (NULL);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT c1, SUBSTR(c1, 1) AS dummy FROM t1 ORDER BY c1 ASC;
+------+-------+
| c1 | dummy |
+------+-------+
| NULL | NULL |
| NULL | NULL |
| | |
| | |
+------+-------+
4 rows in set (0.00 sec)
mysql> SELECT c1, SUBSTR(c1, 1) AS dummy FROM t1 ORDER BY dummy ASC;
+------+-------+
| c1 | dummy |
+------+-------+
| | |
| NULL | NULL |
| | |
| NULL | NULL |
+------+-------+
4 rows in set (0.00 sec)
mysql> SELECT c1, CONCAT(c1, '') AS dummy FROM t1 ORDER BY dummy ASC;
+------+-------+
| c1 | dummy |
+------+-------+
| | |
| NULL | NULL |
| | |
| NULL | NULL |
+------+-------+
4 rows in set (0.00 sec)
mysql> SELECT c1, LTRIM(c1) AS dummy FROM t1 ORDER BY dummy ASC;
+------+-------+
| c1 | dummy |
+------+-------+
| | |
| NULL | NULL |
| | |
| NULL | NULL |
+------+-------+
4 rows in set (0.00 sec)
mysql> SELECT c1, SUBSTR(c1, 1) AS dummy FROM t1 ORDER BY dummy DESC;
+------+-------+
| c1 | dummy |
+------+-------+
| | |
| NULL | NULL |
| | |
| NULL | NULL |
+------+-------+
4 rows in set (0.00 sec)
Suggested fix:
The ORDER BY SUBSTR(c1, 1) ASC returns same result as ORDER BY c1 ASC.