如何实现表中数据先数值后字符串排序(不指定升降序)
实现混合数值/字符串列的分区排序(数值在前,字符串在后)
刚好处理过类似的场景,核心思路是先给数据打个"类型标签"——数值型标记为高优先级(排在前面),字符串型标记为低优先级(排在后面);如果需要保持同一类型内的原始顺序,再结合行号来排序就行。下面是主流数据库的具体实现:
MySQL 版本
MySQL里可以用正则表达式判断是否为纯数字,再用变量生成行号来保留原顺序:
SELECT col FROM ( SELECT col, @row_num := @row_num + 1 AS row_id, -- 纯数字标记为0,其他为1,排序时0在前 CASE WHEN col REGEXP '^[0-9]+$' THEN 0 ELSE 1 END AS is_string FROM your_table, (SELECT @row_num := 0) AS init_var ) AS temp_result ORDER BY is_string, row_id;
要是你希望数值型内部按大小排序,而不是原顺序,把row_id换成CAST(col AS UNSIGNED)就行。
PostgreSQL 版本
PostgreSQL用TRY_CAST判断是否能转成整数会更严谨(比如能识别带小数的数值),搭配ROW_NUMBER()生成行号:
SELECT col FROM ( SELECT col, ROW_NUMBER() OVER () AS row_id, CASE WHEN TRY_CAST(col AS INTEGER) IS NOT NULL THEN 0 ELSE 1 END AS is_string FROM your_table ) AS temp_result ORDER BY is_string, row_id;
同样,想让数值按大小排的话,把row_id改成col::INTEGER即可。
SQL Server 版本
SQL Server用TRY_CONVERT来判断数值类型,ROW_NUMBER()生成行号时要加ORDER BY (SELECT NULL)来保留原表顺序:
SELECT col FROM ( SELECT col, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS row_id, CASE WHEN TRY_CONVERT(INT, col) IS NOT NULL THEN 0 ELSE 1 END AS is_string FROM your_table ) AS temp_result ORDER BY is_string, row_id;
小提示
如果你的列里还有带小数的数值(比如45.5),记得调整判断逻辑——比如MySQL把正则改成^[0-9]+(\.[0-9]+)?$,PostgreSQL和SQL Server把转换类型改成NUMERIC就行。
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

