如果有人输入姓氏/名字/中间名,如何将名字分成名字/中间名/姓氏?订单已知

时间:2019-06-15 21:00:46

标签: sql sql-server

我正在尝试根据指示的顺序将名字分为第一,中间,最后。我对如何执行此操作一无所知,我们将不胜感激。我正在使用sql server 2008。

我附上了示例数据集和我想创建的理想数据集。

ID  ORDER                   NAME
1   first, middle, last     Bruce, Batman, Wayne
2   middle, last, first     Superman, Kent, Clark
3   last, first, middle     Prince, Diana, Wonderwoman

INTO:

ID  ORDER                   NAME
1   first                   Bruce
1   middle                  Batman
1   last                    Wayne
2   middle                  Superman
2   last                    Kent
2   first                   Clark
3   last                    Prince
3   first                   Diana
3   middle                  Wonderwoman

3 个答案:

答案 0 :(得分:0)

SQL Server没有很好的字符串处理功能。不过,您可以使用递归CTE来做到这一点:

with cte as (
      select id,
             convert(varchar(max), left(ord, charindex(',', ord) - 1)) as ord,
             convert(varchar(max), left(name, charindex(',', name) - 1)) as name,
             convert(varchar(max), stuff(ord, 1, charindex(',', ord) + 1, '')) as ord_rest,
             convert(varchar(max), stuff(name, 1, charindex(',', name) + 1, '')) as name_rest,
             1 as lev
      from t
      union all
      select id,
             convert(varchar(max), left(ord_rest, charindex(',', ord_rest + ',') - 1)) as ord,
             convert(varchar(max), left(name_rest, charindex(',', name_rest + ',') - 1)) as name,
             convert(varchar(max), stuff(ord_rest, 1, charindex(',', ord_rest + ',') + 1, '')) as ord_rest,
             convert(varchar(max), stuff(name_rest, 1, charindex(',', name_rest + ',') + 1, '')) as name_rest,
             lev + 1
      from cte
      where ord_rest <> '' and lev < 10
     )
select id, ord, name
from cte
order by id, lev

Here是db <>小提琴。

答案 1 :(得分:0)

借助返回序列的parse / split函数,使用CROSS APPLY变得无关紧要

示例

Device.OpenUri(new Uri("mailto:test@test.com?subject=test&body=test"));

返回

Select A.ID 
      ,B.*
 From  YourTable A
 Cross Apply (
                Select [Order] = B1.RetVal
                      ,[Name]  = B2.RetVal
                 From  [dbo].[tvf-Str-Parse]([ORDER],',') B1
                 Join  [dbo].[tvf-Str-Parse]([NAME] ,',') B2 on B1.RetSeq=B2.RetSeq
             ) B

感兴趣的功能

ID  Order   Name
1   first   Bruce
1   middle  Batman
1   last    Wayne
2   middle  Superman
2   last    Kent
2   first   Clark
3   last    Prince
3   first   Diana
3   middle  Wonderwoman

答案 2 :(得分:0)

我发现其他答案很难遵循-它们肯定是巧妙的窍门,但我认为有人来维护它们可能就像“哇?”。在这里,我在第一个cte中计算逗号的索引(第一个逗号字符串索引在o1 / n1中,第二个逗号在o2 / n2中),将字符串切掉(1和第一个逗号之间的子字符串,第一个之间的子字符串)第二个逗号,第二个逗号,第三个逗号之后的子字符串),然后使用几个并集将结果从7列转换为3

WITH idxs AS
(
SELECT 
  id,
  order,
  name,
  CHARINDEX(',', [order]) as o1,
  CHARINDEX(',', [order], CHARINDEX(',', [order]) + 1) as o2,
  CHARINDEX(',', name) as n1,
  CHARINDEX(',', name, CHARINDEX(',', name) + 1) as n2
FROM
  t
),
cuts as (
SELECT
  id,
  SUBSTRING([order], 1, o1-1) as ord1,
  SUBSTRING([order], o1+1, o2-o1-1) as ord2,
  SUBSTRING([order], o2+1, 4000) as ord3,
  SUBSTRING(name, 1, n1-1) as nam1,
  SUBSTRING(name, n1+1, n2-n1-1) as nam2,
  SUBSTRING(name, n2+1, 4000) as nam3
FROM
  idxs
)

SELECT id, ord1 as [order], nam1 as name FROM cuts
UNION ALL
SELECT id, ord2, nam2 FROM cuts
UNION ALL
SELECT id, ord3, nam3 FROM cuts

请注意,如果您的数据有时带有空格,有时甚至没有空格,您将受益于在输出中使用LTRIM / RTRIM

如果在逗号后空格始终存在,则还可以调整子字符串索引以切出空格(任何x + 1的起始索引将为x + 2,因此长度必须为-2)