如何在SQL中匹配和替换字符串的各个部分

时间:2015-04-08 20:12:33

标签: sql regex vertica

我从我的数据库中提取了一个热门网站列表,但我想要合并来自同一个域的结果。我已经能够通过使用以下部分来做到这一点:

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”在三个地方匹配。

关于如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:2)

我没有Vertica可用,所以我在Oracle SQL中测试了它(它有REGEXP_REPLACE()类似于Vertica的)。不确定Vertica中的CTE语法是什么,但无论如何你都要查询一个表:

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})$', '\1')) AS domain_nm_fix
  FROM d1;

此处REGEXP_REPLACE()的作用是修剪域名中最高级别的子域名(如果存在且超过3个级别)。如果只有三个级别,那么任何东西都不会被替换,因为正则表达式不匹配 - 这就是为什么必须修剪前导.字符的原因。因此,例如,careerone.com.au将保持不变,而my.careerone.com.au将由.careerone.com.au更改为REGEXP_REPLACE(),然后必须从.开始{{1}}修整。

答案 1 :(得分:2)

@David 代码也适用于Vertica,但性能不太好。

您可以使用Vertica自己的内部功能,例如TRIM & REGEXP_REPLACE。 在借用 @David Faber reg exp之后,我对此感兴趣。

select TRIM(LEADING '.' from REGEXP_REPLACE(col_name,'^.*((\.[^.]+){3})$', '\1')) AS fixed_dn from table_name;