求各位有识之士,身份证标准化处理的sql语句应该怎么写,需求如下图
前两行比较好处理:
case when length(trim(id_no))<>15 then upper(id_no)
when length(trim(id_no))=15 then concat(substr(trim(id_no),1,6),'19',substr(trim(id_no),7)) end
第四行也可以直接写:
case when trim(id_no) REGEXP '[^0-9.]'=1 then id_no
第三行的需求只通过一句sql应该是不太好写的,因为涉及到了对一个字符串进行依次遍历,取出里面的数字,这可能需要自己创建函数或者写一个存储过程才能实现这个功能了
1、首先,需求中有两个问题:
一个是:15号的身份证号 + ‘19’是两位长,而除11的余数可能为10,也是两位长,所以最终的身份证号可能是19位长;
另一个是:最后一句话,是输出加了“19”的身份证号还是原始的身份证号,未说清楚(我暂时就输出原始的数据了)
2、其次,我不明白“加权求和”是个啥算法,我只能按求和来处理了
3、解决方法也很简单,一个是判定字符长度(这个所有数据库都支持),另一个是正则表达式判定所有均只含0-9,这个绝大部分数据库都支持,再就是重复劳动提取各个数字并转换为int相加而已……我就以PostGresQL数据库为例给出解决方案:(其他数据库自行对照转换即可):
WITH t AS (
SELECT * FROM ( VALUES( '511111200101013333' ), ( '51111120010101333a' ), ( '511111800101222' ), ( '511a11800101222' ) ) AS t( sfzh ) )
SELECT sfzh
, ( CASE WHEN length( sfzh ) != 15 THEN upper( sfzh )
WHEN sfzh ~ '^[0-9]{15}$' THEN LEFT( sfzh, 5 ) || '19' || RIGHT( sfzh, 10 )
|| ( substr( sfzh, 1, 1 )::int + substr( sfzh, 2, 1 )::int + substr( sfzh, 3, 1 )::int + substr( sfzh, 4, 1 )::int + substr( sfzh, 5, 1 )::int
+ substr( sfzh, 6, 1 )::int + substr( sfzh, 7, 1 )::int + substr( sfzh, 8, 1 )::int + substr( sfzh, 9, 1 )::int + substr( sfzh, 10, 1 )::int
+ substr( sfzh, 11, 1 )::int + substr( sfzh, 12, 1 )::int + substr( sfzh, 13, 1 )::int + substr( sfzh, 14, 1 )::int + substr( sfzh, 15, 1 )::int + 10 ) % 11
ELSE sfzh END ) sfzh1
FROM t;
输出结果(sfzh1字段为需求结果):
代码特别说明:sfzh ~ '^[0-9]{15}$' 表示正则匹配,^表示以[0-9]任一数字开始,{15}表示全部为[0-9]任一数字共15位长,$表示字符串结束
没懂第三个啥意思
with t1 as (
select '511111200101013333' sfz union
select '51111120010101333a' sfz union
select '511111800101222' sfz union
select '511a11800101222' sfz )
select case when length(sfz)!=15 then upper(sfz)
when length(sfz)=15 then concat(concat(substr(sfz,1,6),'19'),substr(sfz,6))
when sfz not regexp '[a-k]' then concat(sfz,floor(sfz/11))
when sfz regexp '[a-k]' then sfz
end sfz1
,length(sfz)
,sfz
,floor(sfz/11)
from t1