MS SQL -- 如何从不一致的长字符串中提取 Phone 数字
MS SQL -- How to Extract Phone Number From Long Inconsistent String
我有一项任务要完成,我必须将大约 970,000 名用户从其他人的数据库导入到我们的数据库中。在源数据库中,有一个 phone 数字字段,其中包含多个 phone 数字连接成一个可怕的字符串。
以下是一些数据示例:
|Home: 555-555-5555 Office: (555)-555-5555 Work: 5555555555|
|Home: Office: 5555-5555 Work: 555-555-5555|
|Office: 555-555-5555 Home: (555)555-5555 some Comment here|
我 运行 遇到的问题是
- 数字顺序不一致
- 散布着一些自由文本评论
- 部分 phone 数字具有不同的格式。
如果可能的话,我真的更愿意通过 SQL 来做到这一点,并且我很难以有效的方式做到这一点,并且需要最少的手动调整。
在我的数据库中,每个 phone 数字类型都有单独的列,因此我基本上需要将这些字符串拆分到适当的列中。
请告诉我是否遗漏了什么。
使用 T-SQL 来完成这个任务并不是最好的选择。最接近的解决方案是创建一个 CLR 程序集,该程序集将利用 .NET 中提供的 RegEx 功能。
不过,您也可以查看 Data Quality Services。它是一个 SQL 服务器组件,专为这种特定类型的任务创建 - 手动条目清理、统一、重复数据删除等。但是,它需要 SQL 服务器的 BI 或企业版。
在此代码中,您将需要 3 个额外的列来存储新的 phone 个数字
这是代码中的逻辑
splitting the phone numbers
cutting off text before first 3 last 3 numerics in the split result
deleting the alien characters used in phone number(only those used in sample)
inserting replacement separators '-' at position 7 and 4
grouping up data
updating table
示例数据:
DECLARE @t table
(phone varchar(500), home varchar(50), work varchar(50), office varchar(50))
INSERT @t(phone) values
('Home: 555-555-5551 Office: (555)-555-5555 Work: 5555555552|'),
('|Home: Office: 5555-5555 Work: 555-555-5555|'),
('|Office: 555-555-5555 Home: (555)555-5555 some Comment here|')
更新:
;WITH CTE as
(
SELECT
nid,work, home, office,
t.c.value('.', 'VARCHAR(2000)') phone
FROM (
SELECT
row_number() over(order by (select 1)) nid, work, home,office,
x = CAST('<t>' +
REPLACE(REPLACE(REPLACE(phone, 'Work', '</t><t>work')
,'Office', '</t><t>Office'), 'Home', '</t><t>Home')
+ '</t>' AS XML)
FROM @t -- replace @t with your table
) a
CROSS APPLY x.nodes('/t') t(c)
WHERE t.c.value('.', 'VARCHAR(2000)') like '%[0-9][0-9][0-9]%'
), CTE2 as
(
SELECT
work,max(case when phone like '%work%' then z end) over(partition by nid)nwork,
home,max(case when phone like '%home%' then z end) over(partition by nid)nhome,
office,max(case when phone like '%office%' then z end) over(partition by nid)noffice
FROM cte t
CROSS APPLY(SELECT REVERSE(SUBSTRING(phone,PATINDEX('%[0-9][0-9][0-9]%', phone), 20))x)y
CROSS APPLY(SELECT STUFF(STUFF(REPLACE(REPLACE(REPLACE(REVERSE(
SUBSTRING(x, PATINDEX('%[0-9][0-9][0-9]%', x), 20)), ')', ''), '\', ''),
'-', ''),7,0, '-'),4,0,'-')z)v )
UPDATE CTE2
SET work = nwork, home = nhome, office = noffice
SELECT home,work,office FROM @t
结果:
home work office
555-555-5551 555-555-5552 555-555-5555
NULL 555-555-5555 555-555-5555
555-555-5555 NULL 555-555-5555
我有一项任务要完成,我必须将大约 970,000 名用户从其他人的数据库导入到我们的数据库中。在源数据库中,有一个 phone 数字字段,其中包含多个 phone 数字连接成一个可怕的字符串。
以下是一些数据示例:
|Home: 555-555-5555 Office: (555)-555-5555 Work: 5555555555|
|Home: Office: 5555-5555 Work: 555-555-5555|
|Office: 555-555-5555 Home: (555)555-5555 some Comment here|
我 运行 遇到的问题是
- 数字顺序不一致
- 散布着一些自由文本评论
- 部分 phone 数字具有不同的格式。
如果可能的话,我真的更愿意通过 SQL 来做到这一点,并且我很难以有效的方式做到这一点,并且需要最少的手动调整。
在我的数据库中,每个 phone 数字类型都有单独的列,因此我基本上需要将这些字符串拆分到适当的列中。
请告诉我是否遗漏了什么。
使用 T-SQL 来完成这个任务并不是最好的选择。最接近的解决方案是创建一个 CLR 程序集,该程序集将利用 .NET 中提供的 RegEx 功能。
不过,您也可以查看 Data Quality Services。它是一个 SQL 服务器组件,专为这种特定类型的任务创建 - 手动条目清理、统一、重复数据删除等。但是,它需要 SQL 服务器的 BI 或企业版。
在此代码中,您将需要 3 个额外的列来存储新的 phone 个数字
这是代码中的逻辑
splitting the phone numbers
cutting off text before first 3 last 3 numerics in the split result
deleting the alien characters used in phone number(only those used in sample)
inserting replacement separators '-' at position 7 and 4
grouping up data
updating table
示例数据:
DECLARE @t table
(phone varchar(500), home varchar(50), work varchar(50), office varchar(50))
INSERT @t(phone) values
('Home: 555-555-5551 Office: (555)-555-5555 Work: 5555555552|'),
('|Home: Office: 5555-5555 Work: 555-555-5555|'),
('|Office: 555-555-5555 Home: (555)555-5555 some Comment here|')
更新:
;WITH CTE as
(
SELECT
nid,work, home, office,
t.c.value('.', 'VARCHAR(2000)') phone
FROM (
SELECT
row_number() over(order by (select 1)) nid, work, home,office,
x = CAST('<t>' +
REPLACE(REPLACE(REPLACE(phone, 'Work', '</t><t>work')
,'Office', '</t><t>Office'), 'Home', '</t><t>Home')
+ '</t>' AS XML)
FROM @t -- replace @t with your table
) a
CROSS APPLY x.nodes('/t') t(c)
WHERE t.c.value('.', 'VARCHAR(2000)') like '%[0-9][0-9][0-9]%'
), CTE2 as
(
SELECT
work,max(case when phone like '%work%' then z end) over(partition by nid)nwork,
home,max(case when phone like '%home%' then z end) over(partition by nid)nhome,
office,max(case when phone like '%office%' then z end) over(partition by nid)noffice
FROM cte t
CROSS APPLY(SELECT REVERSE(SUBSTRING(phone,PATINDEX('%[0-9][0-9][0-9]%', phone), 20))x)y
CROSS APPLY(SELECT STUFF(STUFF(REPLACE(REPLACE(REPLACE(REVERSE(
SUBSTRING(x, PATINDEX('%[0-9][0-9][0-9]%', x), 20)), ')', ''), '\', ''),
'-', ''),7,0, '-'),4,0,'-')z)v )
UPDATE CTE2
SET work = nwork, home = nhome, office = noffice
SELECT home,work,office FROM @t
结果:
home work office
555-555-5551 555-555-5552 555-555-5555
NULL 555-555-5555 555-555-5555
555-555-5555 NULL 555-555-5555