【问题标题】:Split multiple values from a string in one column, into multiple columns using SQL Server使用 SQL Server 将一列中的字符串中的多个值拆分为多列
【发布时间】:2021-11-07 00:16:42
【问题描述】:

我在 SQL Server 中有一个表,它输出以下内容:

CompanyName CompanyNumber Tags
1st Comp Ltd 1 Credit broker;Limited Permission Lender;Insurance Intermediary
business.com 456 Investment Advisor;Credit Broking Only
Charity.org 156789 Not for profit

我想拆分标签列中的值,使每列只有一个标签,所以:

CompanyName CompanyNumber Tag1 Tag2 Tag3
1st Comp Ltd 1 Credit broker Limited Permission Lender Insurance Intermediary
business.com 456 Investment Advisor Credit Broking Only
Charity.org 156789 Not for profit

我可以在 excel 中使用分号作为分隔符手动执行此操作,然后调整标题,但这可以在 SQL Server 中完成吗?最终,我希望在 SQL Server 中有一个视图来格式化数据,这样我就可以让一个 powershell 脚本生成一个 csv 并通过电子邮件发送。

我尝试了以下方法,我想我可能快到了,只是在视图中不起作用:

with TagsDelimited_CTE AS
(select CompanyName, CompanyNumber, Value,
ROW_NUMBER() over(partition by CompanyName, CompanyNumber order by CompanyName, CompanyNumber) as RowNum
from  Source
CROSS APPLY
string_split(Tags,';') 
)
select CompanyName, CompanyNumber,
[1] as Tag1,
[2] as Tag2,
[3] as Tag3
From TagsDelimited_CTE
PIVOT
(MAX(value)
For RowNum in ([1],[2],[3])) as PVT

任何帮助都会有很大帮助,谢谢。

【问题讨论】:

  • 似乎工作正常,也在视图中
  • 它现在也适用于我,我一定是在某个地方犯了错误,抱歉。
  • 表格未规范化。这就是使它工作如此困难的原因。我建议您更改数据库设计(或更改),使其成为应有的关系数据库,并带有单独的 company_tag 表。

标签: sql sql-server multiple-columns delimiter


【解决方案1】:

使用一点 JSON 并假设您有已知或最大数量的标签

Select A.CompanyName
      ,A.CompanyNumber
      ,Tag1  = JSON_VALUE(S,'$[0]')
      ,Tag2  = JSON_VALUE(S,'$[1]')
      ,Tag3  = JSON_VALUE(S,'$[2]')
From  YourTable A
Cross Apply ( values ( '["'+replace(STRING_ESCAPE(Tags,'json'),';','","')+'"]' ) ) B(S)

【讨论】:

  • @Stuart 总是乐于提供帮助
  • @JohnCappelletti 。 . .你和 JSON。这就像黑魔法。
【解决方案2】:

APPLY 中旋转更容易,因为这样您就可以按行进行。

使用MAX(CASE 进行透视通常也更灵活。

请注意,不保证值的顺序

SELECT
  s.CompanyName,
  s.CompanyNumber,
  v.*
FROM Source s
CROSS APPLY (
    SELECT
      MAX(CASE WHEN rn = 1 THEN Value END) AS Tag1,
      MAX(CASE WHEN rn = 2 THEN Value END) AS Tag2,
      MAX(CASE WHEN rn = 3 THEN Value END) AS Tag3      
    FROM (
        SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS rn
        FROM STRING_SPLIT (s.Tags, ';') splitted
    ) v
) v;

【讨论】:

  • 完全仅供参考,但我已经开始使用ORDER BY @@SPID(如果你想强制串行执行,还有ORDER BY @@TRANCOUNT)而不是ORDER BY (SELECT NULL)。与 Paul White、Martin Smith 和 Itzik BenGan hereherehere 进行了一些对话。
  • 谢谢,我确实在我们制作那个系列时看到了那个对话(我是那边的查理),但除了更短的语法之外没有看到任何好处。再看一遍,唯一的好处是它允许一个微不足道的计划,Martin points that out 另外,如果 Erik 不得不将 his website 重命名为 orderbyspid.com,我无法忍受,它只是没有相同的环:- )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
相关资源
最近更新 更多