SQL排序问题:如何按IN子句指定顺序对field_id进行二次排序
没问题!要让查询结果严格按照IN子句里指定的field_id顺序排列,同时还能灵活增减序列里的数值,不同数据库有不同的实用方案,我给你整理了几种主流数据库的实现方式:
解决方案
因为不同数据库对自定义排序的语法支持存在差异,以下是对应主流数据库的具体实现:
1. MySQL/MariaDB 方案
可以用FIELD()函数直接匹配IN子句的序列,它会返回字段值在指定列表中的位置,以此实现自定义排序:
SELECT * FROM dba.form_data WHERE form_id = 207873 AND field_id IN (32015102, 32015100, 32015101, 32015105) ORDER BY FIELD(field_id, 32015102, 32015100, 32015101, 32015105), sub_id, array_number;
说明:FIELD()的第一个参数是要排序的字段,后续参数完全对应IN子句的数值序列。后续增减数值时,只需要同步修改FIELD()里的列表即可,非常便捷。
2. PostgreSQL 方案
PostgreSQL可以借助数组和array_position()函数实现,先把IN子句转为数组匹配,再通过数组位置排序:
SELECT * FROM dba.form_data WHERE form_id = 207873 AND field_id = ANY(ARRAY[32015102, 32015100, 32015101, 32015105]) ORDER BY array_position(ARRAY[32015102, 32015100, 32015101, 32015105], field_id), sub_id, array_number;
说明:= ANY(ARRAY[...])和IN子句效果完全一致,后续修改数值序列时,只需要更新数组内的元素即可。
3. Oracle 方案
Oracle推荐用DECODE()函数实现简洁的自定义排序,也可以用更直观的CASE表达式:
用DECODE()的写法
SELECT * FROM dba.form_data WHERE form_id = 207873 AND field_id IN (32015102, 32015100, 32015101, 32015105) ORDER BY DECODE(field_id, 32015102, 1, 32015100, 2, 32015101, 3, 32015105, 4), sub_id, array_number;
用CASE表达式的写法(更易读)
SELECT * FROM dba.form_data WHERE form_id = 207873 AND field_id IN (32015102, 32015100, 32015101, 32015105) ORDER BY CASE field_id WHEN 32015102 THEN 1 WHEN 32015100 THEN 2 WHEN 32015101 THEN 3 WHEN 32015105 THEN 4 END, sub_id, array_number;
说明:两种写法都是给每个field_id分配一个排序序号,后续增减数值时,同步添加或删除对应的序号映射即可。
4. SQL Server 方案
SQL Server常用CASE表达式实现自定义排序,也可以用CHARINDEX()函数:
用CASE表达式的写法(推荐)
SELECT * FROM dba.form_data WHERE form_id = 207873 AND field_id IN (32015102, 32015100, 32015101, 32015105) ORDER BY CASE field_id WHEN 32015102 THEN 1 WHEN 32015100 THEN 2 WHEN 32015101 THEN 3 WHEN 32015105 THEN 4 END, sub_id, array_number;
用CHARINDEX()的写法
SELECT * FROM dba.form_data WHERE form_id = 207873 AND field_id IN (32015102, 32015100, 32015101, 32015105) ORDER BY CHARINDEX(',' + CAST(field_id AS VARCHAR) + ',', ',32015102,32015100,32015101,32015105,'), sub_id, array_number;
说明:CHARINDEX()通过匹配字符串形式的数值序列来确定排序位置,需要注意给数值前后加逗号避免部分匹配的问题。
通用注意事项
- 无论使用哪种方案,当你增减IN子句里的数值时,一定要同步修改
ORDER BY中的排序规则部分,才能保证排序顺序和IN序列一致。 - 如果你希望优先按field_id的自定义顺序排序,就把自定义排序规则放在
ORDER BY的最前面;如果原有的sub_id和array_number排序优先级更高,调整顺序即可。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

