使用SQL查询从多个完整电子邮件地址检索电子邮件ID

使用SQL查询从多个完整电子邮件地址检索电子邮件ID,sql,sql-server,Sql,Sql Server,使用SQL server 我正在尝试从完整电子邮件地址列表中检索电子邮件id 范例 输入 我已经尝试了下面的查询,但它只提供了一个电子邮件id,而不是全部。一些帮助将不胜感激 SELECT (CASE WHEN to_address LIKE '%<%' THEN SUBSTRING(to_address, CHARINDEX('<',to_address)+1, CHARINDEX('>',to_address) - CHARINDEX('<'

使用SQL server 我正在尝试从完整电子邮件地址列表中检索电子邮件id

范例 输入

我已经尝试了下面的查询,但它只提供了一个电子邮件id,而不是全部。一些帮助将不胜感激

SELECT (CASE WHEN to_address LIKE '%<%'
             THEN SUBSTRING(to_address, CHARINDEX('<',to_address)+1, CHARINDEX('>',to_address) - CHARINDEX('<',to_address)-1)
             ELSE to_address
        END) AS ToAddress
from test

在SQL Server中,可以使用字符串分割:

如果要重新连接它们,请执行以下操作:

select s.emails
from t cross apply
     (select string_agg(replace(stuff(s.value, 1, charindex('<', s.value), ''), '>', ''), ';') as email
      from string_split(t.list, ';') s
     ) s;
编辑:

使用SQL Server早期版本的另一种方法是递归CTE:

with cte as (
      select convert(varchar(max), null) as email,
             convert(varchar(max), emails) as rest,
             convert(varchar(max), '') as output_emails, 0 as lev
      from (values ('"ABCD"<abcd@gmail.com>;"TEST" <test@outlook.com>; ')
           ) v(emails)
      union all
      select replace(stuff(v.el, 1, charindex('<', v.el), ''), '>;', ''),
             stuff(rest, 1, charindex(';', rest), ''),
             concat(output_emails,
                    replace(stuff(v.el, 1, charindex('<', v.el), ''), '>;', ''),
                    ';'),
             lev + 1
      from cte cross apply
           (values (left(rest, charindex(';', rest)))) v(el) 
      where rest <> '' and lev < 5
     )
select output_emails
from (select cte.*, row_number() over (order by lev desc) as seqnum
      from cte
     ) cte
where seqnum = 1;

是一个dbfiddle。

在SQL Server中,可以使用string\u split:

如果要重新连接它们,请执行以下操作:

select s.emails
from t cross apply
     (select string_agg(replace(stuff(s.value, 1, charindex('<', s.value), ''), '>', ''), ';') as email
      from string_split(t.list, ';') s
     ) s;
编辑:

使用SQL Server早期版本的另一种方法是递归CTE:

with cte as (
      select convert(varchar(max), null) as email,
             convert(varchar(max), emails) as rest,
             convert(varchar(max), '') as output_emails, 0 as lev
      from (values ('"ABCD"<abcd@gmail.com>;"TEST" <test@outlook.com>; ')
           ) v(emails)
      union all
      select replace(stuff(v.el, 1, charindex('<', v.el), ''), '>;', ''),
             stuff(rest, 1, charindex(';', rest), ''),
             concat(output_emails,
                    replace(stuff(v.el, 1, charindex('<', v.el), ''), '>;', ''),
                    ';'),
             lev + 1
      from cte cross apply
           (values (left(rest, charindex(';', rest)))) v(el) 
      where rest <> '' and lev < 5
     )
select output_emails
from (select cte.*, row_number() over (order by lev desc) as seqnum
      from cte
     ) cte
where seqnum = 1;

是一个数据库文件。

请用您正在使用的数据库标记您的问题:sql server、oracle、postgresql…?使用sql server请用您正在使用的数据库标记您的问题:sql server、oracle、,postgresql…?使用SQL Server获取错误“string\u agg”不是可识别的内置函数,“string\u split”是无效的对象名@Ayesha。这些都是从SQL Server 2017开始提供的,该版本于三年前发布,所以它并不是那么新。在旧版本中,您需要采取更复杂的方法。我们使用的是ms SQL server 2014,它在递归查询cte的列输出_电子邮件中的锚定和递归部分之间的类似小提琴的类型不匹配中抛出错误。@Ayesha。我包括了一把DB小提琴。此问题在版本之间不会更改。如果合适,您可以将锚定部分中的值转换为varcharmax或nvarcharmax。我认为dbfiddle说明了代码的工作原理。谢谢Gordon Linoff…我在初始查询中使用了CAST..它以varcharmax作为email,CASTemails作为varcharmax作为rest工作,强制转换为nvarcharmax作为输出\u电子邮件设置错误“string\u agg”不是可识别的内置函数“并且对象名称“string\u split”无效@Ayesha。这些都是从SQL Server 2017开始提供的,该版本于三年前发布,所以它并不是那么新。在旧版本中,您需要采取更复杂的方法。我们使用的是ms SQL server 2014,它在递归查询cte的列输出_电子邮件中的锚定和递归部分之间的类似小提琴的类型不匹配中抛出错误。@Ayesha。我包括了一把DB小提琴。此问题在版本之间不会更改。如果合适,您可以将锚定部分中的值转换为varcharmax或nvarcharmax。我认为dbfiddle说明了代码的工作原理。谢谢Gordon Linoff…我在初始查询中使用了CAST。它将CASTnull作为varcharmax作为电子邮件工作,将CASTemails作为varcharmax作为rest工作,将nvarcharmax作为输出电子邮件工作
with cte as (
      select convert(varchar(max), null) as email,
             convert(varchar(max), emails) as rest,
             convert(varchar(max), '') as output_emails, 0 as lev
      from (values ('"ABCD"<abcd@gmail.com>;"TEST" <test@outlook.com>; ')
           ) v(emails)
      union all
      select replace(stuff(v.el, 1, charindex('<', v.el), ''), '>;', ''),
             stuff(rest, 1, charindex(';', rest), ''),
             concat(output_emails,
                    replace(stuff(v.el, 1, charindex('<', v.el), ''), '>;', ''),
                    ';'),
             lev + 1
      from cte cross apply
           (values (left(rest, charindex(';', rest)))) v(el) 
      where rest <> '' and lev < 5
     )
select output_emails
from (select cte.*, row_number() over (order by lev desc) as seqnum
      from cte
     ) cte
where seqnum = 1;