如果您可以控制输出文件格式,那么您最好使用两个(或三个)分隔符,一个用于人员,另一个用于订单项目。如果你能得到第三个,那么就用它把订单项从订单行中拆分出来。
假设数据格式:
Person Name | 1:M [Order]
每个订单都是
order line | item name
您可以简单地将整行提取到单个 nvarchar(max) 列中,然后使用 SQL 分解您需要的数据。
以下是一个这样的例子。
declare @tbl table (d nvarchar(max));
insert into @tbl values('Tanya|1|Pen|2|Book|3|Eraser'),('Raj|11|Eraser|22|Bottle');
declare @base table (id int, person varchar(100),total_orders int, raw_orders varchar(max));
declare @output table (id int, person varchar(100),item_id int, item varchar(100));
with a as
(
select
CHARINDEX('|',d) idx
,d
,ROW_NUMBER() over (order by d) as id /*Or newid()*/
from @tbl
), b as
(
select
id
,SUBSTRING(d,0,idx) person
,SUBSTRING(d,idx+1,LEN(d)-idx+1) order_array
from a
), c as
(
select id, person, order_array
,(select count(1) from string_split(order_array,'|')) /2 orders
from b
)
insert into @base (id,person,total_orders,raw_orders)
select id,person,orders,order_array from c
declare @total_persons int = (select count(1) from @base);
declare @person_enu int = 1;
while @person_enu <= @total_persons
BEGIN
declare @total_orders int = (select total_orders from @base where id = @person_enu);
declare @raw_orders nvarchar(max) = (select raw_orders from @base where id = @person_enu);
declare @order_enu int = 1;
declare @i int = 1;
print CONCAT('Person ', @person_enu, '. Total orders: ', @total_orders);
while @order_enu <= @total_orders
begin
--declare @id int = (select value from string_split(@raw_orders,'|',1) where ordinal = @i);
--declare @val varchar(100) = (select value from string_split(@raw_orders,'|',1) where ordinal = @i+1);
--print concat('Will process order ',@order_enu);
--print concat('ID:',@i, ' Value:', @i+1)
--print concat('ID:',@id, ' Value:', @val)
INSERT INTO @output (id,person,item_id,item)
select b.id,b.person,n.value [item_id], v.value [item] from @base b
cross apply string_split(b.raw_orders,'|',1) n
cross apply string_split(b.raw_orders,'|',1) v
where b.id = @person_enu and n.ordinal = @i and v.ordinal = @i+1;
set @order_enu +=1;
set @i+=2;
end
set @person_enu += 1;
END
select * from @output;