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
我正在处理将一行拆分为多行的查询。 我的查询结果如下:
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