最近碰到个SQL排序的问题,需求是如下insert_time字段,要求有值的排到前面且按照降序排列,

创建测试表,
create table test (id int, insert_time datetime);如果按此格式插入数据,
insert into test values(1, ''),(2, '2026-07-27 00:01:00'),(3, ''),(4, '2026-07-25 00:01:00'),(5, '2026-01-01 00:01:00');可能会提示,
SQL 错误 [1292] [22001]: Data truncation: Incorrect datetime value: '' for column 'insert_time' at row 1原因可能就是MySQL的严格模式(sql_mode)拒绝了空字符串''作为日期字段的输入。sql_mode包含STRICT_TRANS_TABLES或NO_ZERO_DATE等选项,导致空字符串无法转换为合法的日期,
show variables like 'sql_mode';
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION此时,要指定存入NULL到日期字段,
insert into test values(1, NULL),(2, '2026-07-27 00:01:00'),(3, NULL),(4, '2026-07-25 00:01:00'),(5, '2026-01-01 00:01:00');测试数据准备完成了,应该如何满足排序需求?

仅按照insert_time排序,则NULL排前面,
select * from test order by insert_time;
此时,可以指定insert_time is null到order by,非空记录排到前面了,
select * from test order by (insert_time is null);
如上的操作,逻辑上是利用了MySQL数据库中(insert_time IS NULL)是一个布尔表达式,有值时返回0(假),是NULL时返回1(真),默认排序ASC(升序)时,0排在1前面。所以有值的(0)在前,空值的(1)在后。
但是要注意,虽然从显示看,有值的好像已经按照降序排列了,但实际上,所有有值的记录,在数据库内部的顺序是随机的(取决于索引扫描或主键顺序),绝不是严格按insert_time降序排列。因此完整的,
select * from test order by (insert_time is null), insert_time desc;
第一层排序 (insert_time IS NULL):将0(有值)排前面,1(NULL)排后面。
第二层排序(insert_time DESC):只在有值的分组内部,按时间从新到旧(降序)排列。
如上SQL才能保证需求的准确实现。
如果我们深层挖掘下,这条SQL用到的知识基本上都是很基础的,但能不能将不同的知识点整合起来,这就取决于对需求以及知识的理解和结合,当然,现在通过大模型,这种需求可以很容易的实现,但这背后的逻辑,我们还是要掌握,形成我们自己的逻辑和知识库,才能让自己更加有价值,而不仅仅是大模型的搬运工。