如果你問我想你問,你需要動態SQL,正則表達式和樞轉。 動態SQL生成代碼,該代碼將生成具有適當列的表格(因爲它們以#___-
命名,並且有任意數量的字段)。 旋轉將一列值轉換爲每個ID的行。
我習慣於SQL Server,而不是Oracle,而我使用的正則表達式功能是UDF,因爲SQL Server沒有本地Regex功能。所以我的答案只會幫助很多,但可能會給你一個如何解決這個問題的想法。
我想你可以內置在甲骨文正則表達式UDF,我們的正則表達式UDF返回結果集,我可以join
或SQL Server的情況下cross/outer apply
,這讓我Value varchar
與整場比賽和SubMatches xml
所捕獲的子匹配:
create table #A (data varchar(100));
Insert into #A
values ('101,#abc-sds)dfgd)3453)#xyz-hju)dddjfj)eieei)2323');
Insert into #A
values ('102,#abc-ddeff)errr)3434)#xyz-bnhb)hehe)333)#abc-dew)weerr)2343)#efg-3434)34');
declare @cols nvarchar(max), @q nvarchar(max)
-- Gets found columns comma-separated in @cols:
select @cols = isnull(@cols + ', ', '') + substring(r.Value, 2, len(r.Value)-2)
from #A
cross apply dbo.RegexFind(data, '#(\w+)-', 1, 1, 1) r
group by r.Value
-- Dynamically create #B with @cols and insert
set @q = N'create table #B(id int, ' + replace(@cols, ', ', ' varchar(255), ') + ' varchar(255))
insert into #B
select p.*
from (
select r.Value,
a.SubMatches.value(''(//submatch[@index=0]/@value)[1]'', ''varchar(255)'') col,
a.SubMatches.value(''(//submatch[@index=1]/@value)[1]'', ''varchar(255)'') val
from #A
-- Find the ID at the start
cross apply dbo.RegexFind(data, ''^\d+'', 1, 1, 1) r
-- Find any and all #___- occurrences and the text after it
outer apply dbo.RegexFind(data, ''#(\w+)-([^#]+)'', 1, 1, 1) a
) s
pivot (-- Pivot dynamically on the found @cols
min(val) for col in (' + @cols + ')
) p
select * from #B'
exec sp_executesql @q
隨着表#A
您的示例內容這給下面的SQL(的@q
含量):
create table #B(id int, abc varchar(255), efg varchar(255), xyz varchar(255))
insert into #B
select p.*
from (
select r.Value,
a.SubMatches.value('(//submatch[@index=0]/@value)[1]', 'varchar(255)') col,
a.SubMatches.value('(//submatch[@index=1]/@value)[1]', 'varchar(255)') val
from #A
-- Find the ID at the start
cross apply dbo.RegexFind(data, '^\d+', 1, 1, 1) r
-- Find any and all #___- occurrences and the text after it
outer apply dbo.RegexFind(data, '#(\w+)-([^#]+)', 1, 1, 1) a
) s
pivot (-- Pivot dynamically on the found @cols
min(val) for col in (abc, efg, xyz)
) p
select * from #B
注壽呃這個#B
臨時表只存在於動態SQL內部,我不知道Oracle如何處理這個。
不明白如何分割,標記是什麼,顯示更多示例以及如何分割它。 – zaratustra 2014-09-01 10:44:00
你想將一個字符串拆分爲多行*和*列?爲什麼在兩行中重複102的xyz/efg值 - 如果'#abc'是下一個'行'的開始,是不是一行會得到xyz,另一行是efg?你的正則表達式嘗試有多遠? – 2014-09-01 10:45:07