用SQL將字串按分隔符拆為子串
阿新 • • 發佈:2018-12-30
專案中同一個型號包含多個尺碼資訊,這些資訊採用分隔符拼接在一起存放在一個欄位中,現在需要提交每個型號的各個尺碼資訊,也就是說原來一條記錄儲存的,現在需要變成多條記錄。下面給出原始表和插入資料的指令碼:
create table A(Lot_Key varchar(15), F_Size varchar(100)) insert into A select 'CA101', '33.50x1.50x2.50x3.35' union all select 'CA200', '18.50x17.00x1.60' union all select 'CG300', '21.15x1.65x2.50x1.30x1.65' union all select 'CQ255', '31.50x1.75' go
查詢A表中的資料得到如下結果:
圖 1
期望的結果是每條記錄的F_Size按照x進行分隔,轉化成多條記錄,最終得到如下結果:
圖2
這裡考慮採用SUBSTRING函式取子串的方式獲取每個尺碼,引入master..spt_values表,通過該表可以獲取0到2047總共2048個連續的數字,這樣可以定位每個分隔符的索引位置,實現兩個分隔符之間數字的擷取。下面是查詢上圖結果的SQL語句:
select Lot_Key,F_Size, MAX(case when rownum = 1 then v else null end) F_Size01, MAX(case when rownum = 2 then v else null end) F_Size02, MAX(case when rownum = 3 then v else null end) F_Size03, MAX(case when rownum = 4 then v else null end) F_Size04, MAX(case when rownum = 5 then v else null end) F_Size05 from ( select Lot_Key, F_Size, SUBSTRING(t.F_Size, number ,CHARINDEX('x',t.F_Size+'x',number)-number) as v, ROW_NUMBER() over(partition by lot_key order by getdate()) rownum from A t,master..spt_values s where s.number >=1 and s.type = 'P' and SUBSTRING('x'+t.F_Size,s.number,1) = 'x' )t group by Lot_Key,F_Size order by Lot_Key
上面的SQL語句理解起來非常困難,那麼我們抽絲剝繭看它是如何進行字串分隔的。首先看下面的SQL語句:
select * from A t,master..spt_values s
where s.number >=1
and s.type = 'P'
and SUBSTRING('x'+t.F_Size,s.number,1) = 'x'
得到的結果:
圖3
原來的CA101記錄變成了4條記錄,注意number列,1,7,12,17分別是每個分隔符的位置,當然是針對“x33.50x1.50x2.50x3.35”而言。圖3中的記錄數和最終的結果的記錄數是一致的,這個時候就需要在圖3中每個F_Size資料後面加一個x,例如圖3中的第一條記錄為例,就變成了“33.50x1.50x2.50x3.35x”,每次需要首先知道要取的子串的長度,採用下面的語句:
select CHARINDEX('x',t.F_Size+'x',number)-number
以圖3中的第一條記錄為例對上面的語句進行轉化
最終再看看如何取出子串數字
總結
這種方式只能針對字串的長度在一定限度範圍內的,否則就會因master..spt_values表的連續自然數不足,導致後面的沒辦法分割。