SQL 服务器将行拆分为多行

SQL Server Split Row To Multiple Rows

我正在处理将一行拆分为多行的查询。 我的查询结果如下:

     TEXTVALUE
1    Product1 P5 Product2 P19 Product3 P30 Product4 P11 Product5 P23
2    Product3 P30 Product7 P33 
3    Product8 P53 Product5 P23 Product1 P5

我需要将其输出到:

     PRODUCT         AMOUNT
1    Product1        P5
2    Product1        P5
3    Product2        P19
4    Product3        P30
5    Product3        P30
6    Product4        P11
7    Product5        P23
8    Product5        P23
9    Product7        P33
10   Product8        P53

不管有没有重复,我只需要将它们基本上拆分为产品名称和数量即可。

有什么好的指点吗?

非常感谢!

我更喜欢上面链接文章中列出的方法,称为 Moden 分离器。我不使用 Aaron 修改的版本,因此他的比较是一致的。我使用此处发布的原件。 http://www.sqlservercentral.com/articles/Tally+Table/72993/ 您需要先查看该页面并获取该拆分器的代码,然后才能使用此代码。

拆分器相对于大多数其他拆分器的一大优势是它 returns 单个项目的行号。您可以像此处需要的那样很好地利用它进行多级拆分。

这是一个使用计数 table 分离器的完整工作示例。

if OBJECT_ID('tempdb..#something')is not null
    drop table #Something

create table #Something
(
    SomeID int identity, 
    TextValue varchar(500)
)

insert #Something
select 'Product1 P5 Product2 P19 Product3 P30 Product4 P11 Product5 P23' union all
select 'Product3 P30 Product7 P33' union all
select 'Product8 P53 Product5 P23 Product1 P5';

with MySplitData as
(
    select Item
        , ItemNumber
        , SomeID
    from #Something s
    cross apply dbo.DelimitedSplit8K(s.TextValue, ' ') x
)

select p.Product
    , a.Amount
from
(
    select Item as Product
        , ItemNumber
        , SomeID
    from MySplitData
    where ItemNumber % 2 = 1
) p
join
(
    select Item as Amount
        , ItemNumber
        , SomeID
    from MySplitData
    where ItemNumber % 2 = 0
) a on a.ItemNumber = p.ItemNumber + 1
    AND a.SomeID = p.SomeID
order by p.SomeID
    , p.ItemNumber

在这种简单的情况下,拆分可以通过使用 FTS world-breaker 来完成(如果产品名称包含破折号或其他可能强制 FTS 解析器将其拆分为多个术语的字符 - 创建用于拆分的 UDF,如上一个答案中所建议的).可以使用 LEAD 窗口函数获取下一个值(需要 SQL Server 2012 及更高版本。这种方法只会进行一次 table 扫描)。

CREATE TABLE #t (text nvarchar(100))
GO


INSERT INTO #t VALUES
('Product1 P5 Product2 P19 Product3 P30 Product4 P11 Product5 P23'),
('Product3 P30 Product7 P33'),
('Product8 P53 Product5 P23 Product1 P5');


WITH SplittedData AS
(
    SELECT t.display_term AS PRODUCT,
        ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RowNumber,
        LEAD(t.display_term, 1, NULL) OVER(ORDER BY (SELECT 1)) AS AMOUNT
    FROM #t
    CROSS APPLY sys.dm_fts_parser('"' + text + '"', 1033, NULL, 1) t
)
SELECT PRODUCT, AMOUNT
FROM SplittedData
WHERE RowNumber % 2 = 1
ORDER BY PRODUCT


DROP TABLE #t
GO