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 查询将 heightweight 数据提取到它们自己的单独列中?

| height | weight |
-------------------
|   195  |   80   |
|   170  |   65   |
|   160  |   89   |
|   165  |   60.5 |

我想我必须使用substringregexsubstring 似乎不合适,因为字符串中的数据位置不固定。 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】:

使用简单的 SUBSTRINSTR,这将比正则表达式快得多。

让我们看一个有效的测试用例:

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 将值存储在单独的列中

如何在 BigQuery 的标准 SQL 中解析具有不同日期字符串的列中的值

SQL:使用案例在单独的列中查找重复项和标记

组合来自 2 个单独的 SQL 表的列数据

修剪数据并放在单独的列中