如何匹配和替换 SQL 中的字符串部分
How to match and replace sections of a string in SQL
我正在从我的数据库中提取一个热门网站列表,但我想合并来自同一域的结果。我已经能够通过使用 :
部分地做到这一点
REGEXP_REPLACE(site, '%|^www([123])?\.|^m\.|^mobile\.|^desktop\.')) as site
所以 "www.facebook.com" 和 "facebook.com" 或 "m.facebook.com"
- 所有这些都出现在数据库中 - 当我执行 select distinct
.
时被视为相同
但是,我想更进一步,编写一个表达式来查看句点之间的每个字符串。如果在句点之间的三个或更多字符串中连续找到匹配项,那么我想将它们视为相同。我根本无法预测每个可能出现在 "facebook.com" 或任何其他站点之前的字符串。
例如:
"my.careerone.com.au" 和
"careerone.com.au" 三处匹配。
或者"yahoo.realestate.com.au"和"rs.realestate.com.au"三处匹配
关于如何实现这一点有什么想法吗?
我没有可用的 Vertica,因此我在 Oracle SQL 中对此进行了测试(它确实具有与 Vertica 类似的 REGEXP_REPLACE()
)。不确定 Vertica 中的 CTE 语法是什么,但无论如何您都会查询 table:
WITH d1 AS (
SELECT 'my.careerone.com.au' AS domain_nm FROM dual
UNION ALL
SELECT 'careerone.com.au' FROM dual
UNION ALL
SELECT 'yahoo.realestate.com.au' FROM dual
UNION ALL
SELECT 'rs.realestate.com.au' FROM dual
)
SELECT domain_nm, TRIM('.' FROM REGEXP_REPLACE(domain_nm, '^.*((\.[^.]+){3})$', '')) AS domain_nm_fix
FROM d1;
REGEXP_REPLACE()
在这里做的是 trim 域名的最高级别子域,如果它存在并且有超过 3 个级别。如果只有三个级别,则不会替换任何内容,因为正则表达式不匹配——这就是为什么前导 .
字符必须是 trimmed 的原因。因此,例如,careerone.com.au
将保持不变,而 my.careerone.com.au
将被 REGEXP_REPLACE()
更改为 .careerone.com.au
,因此必须从中开始 .
trim医学
@David 代码也可以在 Vertica 中运行,但性能方面可能不太好。
您可以使用 Vertica 自己的内部函数,例如 TRIM & REGEXP_REPLACE
。
在 借用 @David Faber reg exp 之后,我以这个结束。
select TRIM(LEADING '.' from REGEXP_REPLACE(col_name,'^.*((\.[^.]+){3})$', '')) AS fixed_dn from table_name;
我正在从我的数据库中提取一个热门网站列表,但我想合并来自同一域的结果。我已经能够通过使用 :
部分地做到这一点REGEXP_REPLACE(site, '%|^www([123])?\.|^m\.|^mobile\.|^desktop\.')) as site
所以 "www.facebook.com" 和 "facebook.com" 或 "m.facebook.com"
- 所有这些都出现在数据库中 - 当我执行 select distinct
.
但是,我想更进一步,编写一个表达式来查看句点之间的每个字符串。如果在句点之间的三个或更多字符串中连续找到匹配项,那么我想将它们视为相同。我根本无法预测每个可能出现在 "facebook.com" 或任何其他站点之前的字符串。
例如: "my.careerone.com.au" 和 "careerone.com.au" 三处匹配。
或者"yahoo.realestate.com.au"和"rs.realestate.com.au"三处匹配
关于如何实现这一点有什么想法吗?
我没有可用的 Vertica,因此我在 Oracle SQL 中对此进行了测试(它确实具有与 Vertica 类似的 REGEXP_REPLACE()
)。不确定 Vertica 中的 CTE 语法是什么,但无论如何您都会查询 table:
WITH d1 AS (
SELECT 'my.careerone.com.au' AS domain_nm FROM dual
UNION ALL
SELECT 'careerone.com.au' FROM dual
UNION ALL
SELECT 'yahoo.realestate.com.au' FROM dual
UNION ALL
SELECT 'rs.realestate.com.au' FROM dual
)
SELECT domain_nm, TRIM('.' FROM REGEXP_REPLACE(domain_nm, '^.*((\.[^.]+){3})$', '')) AS domain_nm_fix
FROM d1;
REGEXP_REPLACE()
在这里做的是 trim 域名的最高级别子域,如果它存在并且有超过 3 个级别。如果只有三个级别,则不会替换任何内容,因为正则表达式不匹配——这就是为什么前导 .
字符必须是 trimmed 的原因。因此,例如,careerone.com.au
将保持不变,而 my.careerone.com.au
将被 REGEXP_REPLACE()
更改为 .careerone.com.au
,因此必须从中开始 .
trim医学
@David 代码也可以在 Vertica 中运行,但性能方面可能不太好。
您可以使用 Vertica 自己的内部函数,例如 TRIM & REGEXP_REPLACE
。
在 借用 @David Faber reg exp 之后,我以这个结束。
select TRIM(LEADING '.' from REGEXP_REPLACE(col_name,'^.*((\.[^.]+){3})$', '')) AS fixed_dn from table_name;