从 MySql 查询的 select 列中提取文本

Extract text from column in select of MySql query

我有一个名为 sentEmails 的 table,其中 body 列包含电子邮件的正文。

在正文中,有一个子字符串如下:

some link: <a href="https://somelink@somesite.com/somePage.php?someVar=someVal&sentby=agent">Random link text

使用 MySql,我需要从此列中提取 url,例如 https://somelink@somesite.com/somePage.php?someVar=someVal&sentby=agent

我在想像下面这样的东西可以通过找到起始位置并返回接下来的 150 个字符来工作,当然它实际上只是 returns 前 150 个字符。

SELECT LEFT(body, LOCATE('some link: <a href="', body)+150)  AS link
FROM sentEmails
WHERE sent between date_sub(now(),INTERVAL 1 WEEK) and now()
AND body like '%some link:%'
AND toEmail = 'email@gmail.com'

附加信息:

如果您在 URL 周围有两个唯一的分隔符,那么可以只使用 SUBSTRING() 来隔离它。一种方法是将锚标记中 URL 的两侧替换为分隔符:

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(
    REPLACE(REPLACE(body, '<a href="', '~'), '&sentby=agent">', '&sentby=agent~'), '~', -2),
    '~', 1)
FROM sentEmails
WHERE sent BETWEEN DATE_SUB(NOW(), INTERVAL 1 WEEK) AND NOW() AND
    body LIKE '%some link:%' AND
    toEmail = 'email@gmail.com'

我用 ~ 替换了 <a href="">。如果 ~ 没有出现在 body 列的任何地方,并且正文中只有一个 HTML 标签,那么这应该有效。

如果 body 列只是 HTML 的一大块,那么您应该考虑使用 xpath 并在您的应用程序层中处理它。

做这种搜索不方便。随着电子邮件的 table 越来越大,查询的性能会越来越差。

如果这是您正在构建的新应用程序,您最好保留一个单独的 table,其中包含每封已发送电子邮件中使用的 URL 列表。您可以在发送电子邮件时将 URL 写入数据库。

这样做的原因是应用程序在数据库中进行的搜索比发送电子邮件要多。因此,通过在发送电子邮件时做一些额外的工作,您可以极大地帮助该功能的最昂贵用途,即搜索。

如果您仍然决定保留当前的方法,您将需要一个包含按此顺序排列的列 (toEmail, sent) 的索引。

除此之外,您的方法很有意义并且会奏效。你真的试过了吗?它对你有用吗?

如果你只是想把 link 提取出来,你能做 instr() 和 mid 函数吗?像这样

select mid(body,substr(body,'="'),substr(body,'">')-substr(body,'="')) from email...

substr(body,'="') = link 的开始位置 =" 和 substr(body,'">') 是 link 的结束位置。

MID 函数取 (str,pos,len) 和 len = 结束位置 - 起始位置

多亏了 Tim 的帮助,我才能够使用以下查询来解决这个问题:

SELECT SUBSTRING_INDEX( SUBSTRING_INDEX(body, 'some link:  <a href="', -1) , 'sentby=agent">', 1) AS link
FROM sentEmails
where sent between date_sub(now(),INTERVAL 1 WEEK) and now()
AND body like '%some link:%'
AND toEmail = 'email@gmail.com'