【SQL】SQL-管好你的字符串

【SQL】SQL-管好你的字符串

  • 一、引言
  • 二、基础加工类(最高频,必须熟练)
    • [1. CONCAT / CONCAT_WS:字符串拼接](#1. CONCAT / CONCAT_WS:字符串拼接)
    • [2. SUBSTR/SUBSTRING:子串截取](#2. SUBSTR/SUBSTRING:子串截取)
    • [3. TRIM / LTRIM / RTRIM:去空格](#3. TRIM / LTRIM / RTRIM:去空格)
    • [4. LOWER / UPPER:大小写 这个容易理解](#4. LOWER / UPPER:大小写 这个容易理解)
  • 三、填充与替换
    • [1. LPAD / RPAD:补位对齐](#1. LPAD / RPAD:补位对齐)
    • [2. REPLACE / REGEXP_REPLACE:替换](#2. REPLACE / REGEXP_REPLACE:替换)
  • 四、正则提取:REGEXP_EXTRACT
  • [五、JSON解析:GET_JSON_OBJECT / JSON_TUPLE(爬虫抓取/文本解析贼好用)](#五、JSON解析:GET_JSON_OBJECT / JSON_TUPLE(爬虫抓取/文本解析贼好用))
    • [1. GET_JSON_OBJECT:单字段提取](#1. GET_JSON_OBJECT:单字段提取)
    • [2. JSON_TUPLE:多字段一次提取](#2. JSON_TUPLE:多字段一次提取)
  • [六、切分与URL解析(需要理解下LATERAL VIEW EXPLODE)](#六、切分与URL解析(需要理解下LATERAL VIEW EXPLODE))
    • [1. SPLIT / SPLIT_PART:字符串拆分](#1. SPLIT / SPLIT_PART:字符串拆分)
    • [2. PARSE_URL:URL解析 => 网址解析神器](#2. PARSE_URL:URL解析 => 网址解析神器)
  • 七、总结对比

一、引言

今天写 Hive 里字符串函数的故事。

数据岗相关的同学,最头疼的一定是数据清洗模块。清洗不到位,计算、分析时会出现各种问题,其中以字符串清洗尤甚:字段涉及拼接、截取、空位处理、JSON解析、URL拆解等......稍不留神,脏数据就悄悄溜进去了。

管好你的字符串,不是说说而已。


二、基础加工类(最高频,必须熟练)

1. CONCAT / CONCAT_WS:字符串拼接

sql 复制代码
-- CONCAT:简单拼接,无分隔符
SELECT CONCAT('Hello', ' ', '点个关注') AS rt;
-- 输出:Hello 点个关注

-- 拼接多个字段生成业务主键
SELECT CONCAT(region, '_', city, '_', user_id) AS biz_key
FROM user;
-- 输出:region_city_user_id  替换具体值 

-- ⚠️ 注意:CONCAT 任一参数为 NULL,结果就是 NULL,不能有脏数据
SELECT CONCAT('Hello', NULL, '点个关注');  -- 返回 NULL
sql 复制代码
-- CONCAT_WS:带分隔符拼接(WS = With Separator)
SELECT CONCAT_WS('-', '2026', '04', '24') AS date_str;
-- 输出:2026-04-24

-- 多字段用逗号拼接
SELECT CONCAT_WS(',', tag1, tag2, tag3) AS tags
FROM product_tags;

-- ⚠️ CONCAT_WS 会自动跳过 NULL,不会导致整体变 NULL
SELECT CONCAT_WS('-', '2026', NULL, '24');  -- 输出:2026--24

总结:看到差别了么,CONCAT / CONCAT_WS除了null值外,还有重复拼接的差异


2. SUBSTR/SUBSTRING:子串截取

sql 复制代码
-- SUBSTR(string, start, length)
-- start 从1开始,正数从左、负数从右,长度几位

-- 截取日期中的年月
SELECT SUBSTR('2026-04-24', 1, 7) AS year_month;
-- 输出:2026-04

-- 截取手机号后4位
SELECT SUBSTR('12345678', -4) AS last_4;
-- 输出:5678

3. TRIM / LTRIM / RTRIM:去空格

sql 复制代码
-- TRIM:去掉两端空格
SELECT TRIM('  Hello 点个关注  ') AS result;
-- 输出:Hello 点个关注

-- LTRIM:只去掉左端空格
SELECT LTRIM('  Hello 点个关注  ') AS result;
-- 输出:Hello World  (这里有个空格)

-- RTRIM:只去掉右端空格
SELECT RTRIM('  Hello 点个关注  ') AS result;
-- 输出:(这里有个空格)  Hello 点个关注

划重点:TRIM 只去空格,如果要去其他字符可以用 TRIM(BOTH 'x' FROM 'xxxHelloxxx'),其他场景可以用 REGEXP_REPLACEREPLACE等其他方式。


4. LOWER / UPPER:大小写 这个容易理解

sql 复制代码
-- LOWER:转小写
SELECT LOWER('Hello 点个关注') AS rt;
-- 输出:hello 点个关注

-- UPPER:转大写
SELECT UPPER('Hello 点个关注') AS rt;
-- 输出:HELLO 点个关注

三、填充与替换

1. LPAD / RPAD:补位对齐

sql 复制代码
-- LPAD:左补齐(右侧对齐)
SELECT LPAD('24', 4, '0') AS result;
-- 输出:0024

-- RPAD:右补齐(左侧对齐)
SELECT RPAD('24', 4, 'x') AS result;
-- 输出:24xx

划重点:LPAD 在做报表对齐、编码补零时特别好用。


2. REPLACE / REGEXP_REPLACE:替换

sql 复制代码
-- REPLACE:简单字符串替换
SELECT REPLACE('Hello 点个关注', '点个关注', '收藏') AS rt;
-- 输出:Hello 收藏

-- 批量替换敏感词
SELECT REPLACE(REPLACE(phone, SUBSTR(phone, 4, 4), '****'), email, '***@***.com') AS info
FROM user;
sql 复制代码
-- REGEXP_REPLACE:正则替换,灵活度最好
-- 去掉所有非数字字符
SELECT REGEXP_REPLACE('Phone: 123-1234-5678', '[^0-9]', '') AS rt;
-- 输出:12312345678

-- 去掉多余空格(多个连续空格变一个)
SELECT REGEXP_REPLACE('Hello   点个关注   SQL', '\\s+', ' ') AS rt;
-- 输出:Hello 点个关注 SQL

-- 去掉字符串中的 HTML 标签
SELECT REGEXP_REPLACE('<p>Hello <b>点个关注</b></p>', '<[^>]+>', '') AS rt;
-- 输出:Hello 点个关注
sql 复制代码
-- 实战:手机号脱敏
SELECT phone,
       REGEXP_REPLACE(phone, '(\\d{3})\\d{4}(\\d{4})', '$1****$2') AS masked_phone
FROM user;
-- 输出:138****5678

划重点:简单替换用 REPLACE,有规律的替换用 REGEXP_REPLACE,正则是最牛的。


四、正则提取:REGEXP_EXTRACT

sql 复制代码
-- REGEXP_EXTRACT(string, pattern, group)
-- group=0 返回整个匹配,group=1 返回第一个捕获组

-- 提取邮箱域名
SELECT REGEXP_EXTRACT('user@example.com', '@([a-zA-Z0-9.]+)', 1) AS domain;
-- 输出:example.com

-- 提取 URL 中的域名
SELECT REGEXP_EXTRACT('https://www.example.com/path?id=1', 'https?://([^/]+)', 1) AS host;
-- 输出:www.example.com

-- 提取中文字符
SELECT REGEXP_EXTRACT('订单号ORD20260424已发货', '([\\u4e00-\\u9fa5]+)', 1) AS chinese;
-- 输出:订单号

划重点:REGEXP_EXTRACT 配合 group 参数能精准提取,比 SUBSTR + INSTR 的组合优雅太多。


五、JSON解析:GET_JSON_OBJECT / JSON_TUPLE(爬虫抓取/文本解析贼好用)

1. GET_JSON_OBJECT:单字段提取

JSON首先得理解Key-Value 的k-v组合形式,键值对。

sql 复制代码
-- 从 JSON 字符串提取字段
SELECT
    GET_JSON_OBJECT('{"name":"四叔","age":100,"city":"杭州"}', '$.name') AS name,
    GET_JSON_OBJECT('{"name":"四叔","age":100,"city":"杭州"}', '$.age')  AS age,
    GET_JSON_OBJECT('{"name":"四叔","age":100,"city":"杭州"}', '$.city') AS city;
-- 输出:四叔 | 100 | 杭州
sql 复制代码
-- 提取嵌套 JSON
SELECT GET_JSON_OBJECT(
        '{"user":{"name":"四叔","address":{"city":"杭州","zip":"100000"}}}',
        '$.user.name'
          ) AS name,
       GET_JSON_OBJECT(
        '{"user":{"name":"四叔","address":{"city":"杭州","zip":"100000"}}}',
        '$.user.address.city'
        ) AS city;
-- 输出:四叔 | 杭州```

```sql
-- 提取数组元素
SELECT GET_JSON_OBJECT(
        '{"items":[{"id":1,"name":"A"},{"id":2,"name":"B"}]}',
        '$.items[0].name'
        ) AS first_item;
-- 输出:A

⚠️ 注意:推荐先执行 SET odps.sql.udf.getjsonobj.new=true; 开启新模式,避免转义问题。


2. JSON_TUPLE:多字段一次提取

sql 复制代码
-- JSON_TUPLE 一次提取多个字段,比多次调用 GET_JSON_OBJECT 会更高效一些
SELECT json_str,
       t.name,
       t.age,
       t.city
FROM user_json
LATERAL VIEW JSON_TUPLE(json_str, 'name', 'age', 'city') t AS name, age, city;
sql 复制代码
-- 实战:解析埋点日志中的 JSON 字段
SELECT log_id,
       t.event_name,
       t.page_url,
       t.user_id,
       t.duration
FROM event_log
LATERAL VIEW JSON_TUPLE(event_data, 'eventName', 'pageUrl', 'userId', 'duration') t AS event_name, page_url, user_id, duration
WHERE dt = '${bizdate}';

划重点:提取1个字段用 GET_JSON_OBJECT,提取多个字段用 JSON_TUPLE + LATERAL VIEW,性能更好。


六、切分与URL解析(需要理解下LATERAL VIEW EXPLODE)

1. SPLIT / SPLIT_PART:字符串拆分

sql 复制代码
-- SPLIT:按分隔符拆分,返回数组
SELECT SPLIT('看,海,的,四,叔', ',') AS result;
-- 输出:["看","海","的","四","叔"]

-- 配合 LATERAL VIEW 展开数组
SELECT  user_id,
        tag
FROM user_info
LATERAL VIEW EXPLODE(SPLIT(tags, ',')) t AS tag;
sql 复制代码
-- SPLIT_PART:直接取拆分后的第N部分(从1开始)
SELECT SPLIT_PART('2026-04-24', '-', 1) AS year,
       SPLIT_PART('2026-04-24', '-', 2) AS month,
       SPLIT_PART('2026-04-24', '-', 3) AS day;
-- 输出:2026 | 04 | 24

划重点:取固定位置用 SPLIT_PART 更简洁;需要展开全部元素用 SPLIT + EXPLODE


2. PARSE_URL:URL解析 => 网址解析神器

sql 复制代码
-- PARSE_URL:提取 URL 的各个部分
SELECT PARSE_URL('https://www.example.com:8080/path/page?id=42&name=test#section', 'HOST') AS host,
       PARSE_URL('https://www.example.com:8080/path/page?id=42&name=test#section', 'PATH') AS path,
       PARSE_URL('https://www.example.com:8080/path/page?id=42&name=test#section', 'QUERY') AS query,
       PARSE_URL('https://www.example.com:8080/path/page?id=42&name=test#section', 'REF') AS ref,
       PARSE_URL('https://www.example.com:8080/path/page?id=42&name=test#section', 'PROTOCOL') AS protocol,
       PARSE_URL('https://www.example.com:8080/path/page?id=42&name=test#section', 'PORT') AS port;
-- 输出:
-- host: www.example.com
-- path: /path/page
-- query: id=42&name=test
-- ref: section
-- protocol: https
-- port: 8080
sql 复制代码
-- 提取指定查询参数
SELECT url,
  	   PARSE_URL(url, 'QUERY', 'id')   AS param_id,
     	 PARSE_URL(url, 'QUERY', 'name') AS param_name
FROM access_log;
-- 输出:id | name
sql 复制代码
-- 实战:流量来源分析
SELECT PARSE_URL(referrer_url, 'HOST') AS source_domain,
  	   PARSE_URL(referrer_url, 'QUERY', 'utm_source') AS utm_source,
    	   PARSE_URL(referrer_url, 'QUERY', 'utm_medium') AS utm_medium,
   	   COUNT(*) AS pv
FROM page_view_log
WHERE referrer_url IS NOT NULL
GROUP BY PARSE_URL(referrer_url, 'HOST'),
  		  PARSE_URL(referrer_url, 'QUERY', 'utm_source'),
   		  PARSE_URL(referrer_url, 'QUERY', 'utm_medium')
ORDER BY pv DESC
LIMIT 20;

划重点:PARSE_URL 第三个参数可指定 QUERY 中的具体 key。


七、总结对比

模块 常用函数 典型场景
基础加工 CONCAT/CONCAT_WS, SUBSTR, TRIM, LOWER/UPPER 拼接、截取、清洗、统一格式
填充与替换 LPAD/RPAD, REPLACE, REGEXP_REPLACE 补零、脱敏、去特殊字符
正则提取 REGEXP_EXTRACT 日志解析、关键信息提取
JSON解析 GET_JSON_OBJECT, JSON_TUPLE 埋点数据、嵌套字段提取
切分与URL SPLIT/SPLIT_PART, PARSE_URL 多值字段展开、流量分析

管好你的字符串~ 字符串清洗要在数据入仓的第一层就做好哦,避免脏数据流入。

今天的分享就到这里,觉得有用动动小手点赞+关注+收藏,一键三连~ 有问题留言沟通啦~

相关推荐
坚持就完事了3 小时前
YARN资源管理器
大数据·linux·hadoop·学习
秋93 小时前
TiDB 数据库全链路实战指南:从下载部署到 Java 高并发调优
java·数据库·tidb
Mr数据杨3 小时前
飞船乘客状态预测与金融风控建模启发
大数据·机器学习·数据分析·kaggle
zhou周大哥3 小时前
银河麒麟安装mysql
数据库·mysql
金融小师妹3 小时前
AI治理框架下的货币政策接续:鲍威尔理事留任机制与决策权迁移的系统博弈
大数据·人工智能·逻辑回归·能源
无敌的黑星星3 小时前
Spring @Transactional 注解全解析
java·数据库·oracle
Fullde福德负载箱厂家3 小时前
负载箱的隐性成本与全周期经济性:用户应知的持有成本与价值管理
大数据·安全·制造
程序鉴定师3 小时前
深圳小程序制作哪家好?2026深度市场分析与选择指南?
大数据·小程序
Rust研习社3 小时前
Rust + PostgreSQL 极简技术栈应用开发
开发语言·数据库·后端·http·postgresql·rust