如何提取数字奇数位及在SELECT语句中实现该需求
嘿,我来帮你搞定这个提取数字(比如EMPNO)奇数位置字符的需求!针对你举的例子——EMPNO为7369时要得到76,不同的SQL数据库有不同的实现方式,我给你整理几种常用的方案:
1. Oracle 数据库实现
如果是Oracle,推荐用层级查询结合LISTAGG来处理任意长度的EMPNO,通用型很强:
SELECT EMPNO, LISTAGG(SUBSTR(TO_CHAR(EMPNO), LEVEL, 1), '') WITHIN GROUP (ORDER BY LEVEL) AS ODD_POS_CHARS FROM EMP WHERE MOD(LEVEL, 2) = 1 CONNECT BY LEVEL <= LENGTH(TO_CHAR(EMPNO)) AND PRIOR EMPNO = EMPNO AND PRIOR SYS_GUID() IS NOT NULL GROUP BY EMPNO;
- 先把数字类型的EMPNO转成字符串(
TO_CHAR(EMPNO)),方便按位置提取字符 - 用
LEVEL遍历每个字符位置,筛选出奇数位置(MOD(LEVEL, 2) = 1) - 最后用
LISTAGG把所有奇数位置的字符拼接成结果 PRIOR SYS_GUID()是为了避免层级查询出现循环问题
如果你的EMPNO长度固定(比如都是4位),直接拼接更高效:
SELECT EMPNO, SUBSTR(TO_CHAR(EMPNO), 1, 1) || SUBSTR(TO_CHAR(EMPNO), 3, 1) AS ODD_POS_CHARS FROM EMP;
2. MySQL 数据库实现(8.0+ 支持递归CTE)
MySQL 8.0及以上版本可以用递归CTE来实现任意长度的提取:
WITH RECURSIVE pos_cte AS ( SELECT EMPNO, CAST(EMPNO AS CHAR) AS emp_str, 1 AS pos, SUBSTR(CAST(EMPNO AS CHAR), 1, 1) AS odd_chars FROM EMP UNION ALL SELECT EMPNO, emp_str, pos + 2, CONCAT(odd_chars, SUBSTR(emp_str, pos + 2, 1)) FROM pos_cte WHERE pos + 2 <= LENGTH(emp_str) ) SELECT EMPNO, MAX(odd_chars) AS ODD_POS_CHARS FROM pos_cte GROUP BY EMPNO;
- 递归CTE从第1位开始,每次跳2位(直接取下一个奇数位置),逐步拼接字符
- 最后用
MAX(odd_chars)拿到完整的拼接结果
3. SQL Server 数据库实现
SQL Server的思路和MySQL类似,用递归CTE结合SUBSTRING和CONCAT:
WITH pos_cte AS ( SELECT EMPNO, CAST(EMPNO AS VARCHAR(20)) AS emp_str, 1 AS pos, SUBSTRING(CAST(EMPNO AS VARCHAR(20)), 1, 1) AS odd_chars FROM EMP UNION ALL SELECT EMPNO, emp_str, pos + 2, CONCAT(odd_chars, SUBSTRING(emp_str, pos + 2, 1)) FROM pos_cte WHERE pos + 2 <= LEN(emp_str) ) SELECT EMPNO, MAX(odd_chars) AS ODD_POS_CHARS FROM pos_cte GROUP BY EMPNO;
注意事项
不管用哪种数据库,一定要先把数字类型的字段转换成字符串类型,因为SUBSTR/SUBSTRING这类按位置提取的函数是针对字符串操作的。如果字段长度固定,直接逐个提取拼接的性能会比递归/层级查询更好哦。
内容的提问来源于stack exchange,提问作者Giulio Angioli
相关产品推荐
相关产品推荐

