SQL Server将行拆分为多行

时间:2015-12-02 19:02:31

标签: sql-server split string-split

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

     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

无论重复,我只需要在产品名称和金额之间进行基本分割。

有什么好的指示吗?

非常感谢!

2 个答案:

答案 0 :(得分:2)

在这个简单的情况下拆分可以通过使用FTS世界破坏者来完成(如果产品名称包含破折号或其他字符,可以强制FTS解析器将其拆分为多个术语 - 创建UDF进行拆分,如前面的答案所示)。使用LEAD窗口函数(SQL Server 2012和需要上限)可以获得下一个值。这种方法只能进行一次表扫描。

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

答案 1 :(得分:1)

我倾向于选择上面链接文章中列出的方法,称为Moden分割器。我不使用Aaron修改的版本,以便他的比较是一致的。我在这里发布原文。 http://www.sqlservercentral.com/articles/Tally+Table/72993/在此代码生效之前,您需要查看该页面并获取该拆分器的代码。

分割器优于大多数其他产品的一大优势是它返回单个项目的行号。你可以在这里很好地利用它来进行多级分割。

以下是使用计数表分割器的完整工作示例。

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