SQL 解析数字数据的列字符串并存储在单独的列中
Posted
技术标签:
【中文标题】SQL 解析数字数据的列字符串并存储在单独的列中【英文标题】:SQL parse column string for numerical data and store in separate columns 【发布时间】:2015-03-12 04:44:29 【问题描述】:我正在使用 Oracle SQL,并且想从通常像这样的单列字符串中解析
suitjacket 899, height195cm weight80kg male
blazerjacket 1099, height170cm weight65kg female
pants 299, height160cm weight89kgs male
coat 1099, height165cms weight60.5kg female
请注意,有时单位是复数形式,末尾带有额外的“s”。如何使用符合 Oracle 标准的 SQL 查询将 height
和 weight
数据提取到它们自己的单独列中?
| height | weight |
-------------------
| 195 | 80 |
| 170 | 65 |
| 160 | 89 |
| 165 | 60.5 |
我想我必须使用substring
或regex
。 substring
似乎不合适,因为字符串中的数据位置不固定。 regex
似乎更好,但我不确定如何制作regex
,然后将其存储在单独的列中,一列用于height
,另一列用于weight
。
【问题讨论】:
我认为这是一个简单的 SUBSTR 和 INSTR 用例。我已经编辑了问题并格式化了。投票重新提出问题。 我看到问题现在重新打开,请参阅我建议的 SUBSTR 和 INSTR 的答案。 【参考方案1】:给定一个示例设置:
CREATE TABLE tbl
(field varchar(48));
INSERT INTO tbl (field) VALUES ('suitjacket 899, height195cm weight80kg male');
INSERT INTO tbl (field) VALUES ('blazerjacket 1099, height170cm weight65kg female');
INSERT INTO tbl (field) VALUES ('pants 299, height160cm weight89kgs male');
INSERT INTO tbl (field) VALUES ('coat 1099, height165cms weight60.5kg female');
您可以结合使用 regexp_substr 和 replace 函数,如下所示:
select to_number(regexp_substr(field, 'height(\d+\.?\d+)', 1, 1, 'i', 1)) height,
to_number(regexp_substr(field, 'weight(\d+\.?\d+)', 1, 1, 'i', 1)) weight
from tbl;
这是上面的demo。以下是一些参考资料:regexp_substr、replace、regex cheat sheet
祝你好运!
【讨论】:
你不需要REPLACE()
;您可以使用在REGEXP_SUSBTR()
. 中指定要返回的子表达式,因此:regexp_substr(s, 'height(\d+\.?\d+)', 1, 1, 'i', 1) as height
(您可能应该在转换后显式转换为数字)。
@Ben 感谢您的洞察力。我编辑了我的答案和 sqlfiddle 演示以反映您的建议。【参考方案2】:
使用简单的 SUBSTR 和 INSTR,这将比正则表达式快得多。
让我们看一个有效的测试用例:
SQL> WITH DATA AS(
2 SELECT 'suitjacket 899, height195cm weight80kg male' str FROM dual UNION ALL
3 SELECT 'blazerjacket 1099, height170cm weight65kg female' str FROM dual UNION ALL
4 SELECT 'pants 299, height160cm weight89kgs male' str FROM dual UNION ALL
5 SELECT 'coat 1099, height165cms weight60.5kg female' str FROM dual
6 )
7 SELECT
8 SUBSTR(str, instr(str, 'height', 1) + LENGTH('height'), instr(str, 'cm', 1) - instr(str, 'height', 1) - LENGTH('height')) height,
9 SUBSTR(str, instr(str, 'weight', 1) + LENGTH('weight'), instr(str, 'kg', 1) - instr(str, 'weight', 1) - LENGTH('weight')) weight,
10 str
11 FROM DATA
12 /
HEIGHT WEIGHT STR
---------- ---------- ----------------------------------------------------------------------------------------------------
195 80 suitjacket 899, height195cm weight80kg male
170 65 blazerjacket 1099, height170cm weight65kg female
160 89 pants 299, height160cm weight89kgs male
165 60.5 coat 1099, height165cms weight60.5kg female
SQL>
您的查询(将 table_name 替换为您的实际表):
SELECT SUBSTR(str, instr(str, 'height', 1) + LENGTH('height'), instr(str, 'cm', 1) - instr(str, 'height', 1) - LENGTH('height')) height,
SUBSTR(str, instr(str, 'weight', 1) + LENGTH('weight'), instr(str, 'kg', 1) - instr(str, 'weight', 1) - LENGTH('weight')) weight,
str
FROM table_name
/
【讨论】:
以上是关于SQL 解析数字数据的列字符串并存储在单独的列中的主要内容,如果未能解决你的问题,请参考以下文章
将 Spark Dataframe 中的多个列发送到外部 API 并将结果存储在单独的列中
当前行和上一行之间的秒数差异,并使用 google bigquery 将值存储在单独的列中