[英]convert xml string in a sql table to dynamic columns
我有兩個表(使用表變量進行說明。您可以直接在管理工作室中運行這些表)與Id列相關。
第一個表中的項具有一些標准列,第二個表具有一些相同記錄的擴展參數數據。 我將擴展集存儲為xml,因為它在所有方面都是動態的(每個產品不同或者添加新值等)。
我可以加入這兩個表並將列列表展平,如下面的示例所示。 但我的查詢要求事先定義動態列。 我希望這個真正的動態,如果我要在@extended表中添加一個新列,它應該自動作為輸出列列表中的新列出現。
基本上,附加列的列表應由該記錄的xml確定。 列名應為xml標記,值應為每個id的xml標記的值。
有什么指針嗎? (並且每張表中的記錄大約100k或更多,也可以很快)
declare @standard table
(
Id INT,
Column1 varchar(10),
Column2 varchar(10),
Column3 varchar(10)
)
declare @extended table
(
Id INT,
column1 xml
)
insert into @standard values (1,'11', '12', '13')
insert into @standard values (2,'21', '22', '23')
insert into @extended values (1,'<FieldSet><Field><id>1</id><column4>1x</column4><column5>4x</column5></Field></FieldSet>')
insert into @extended values (2,'<FieldSet><Field><id>2</id><column4>2x</column4><column5>5x</column5></Field></FieldSet>')
select s.column1, s.column2,
(
SELECT Item2.value('(column4)[1]', 'varchar(50)')
FROM
e.column1.nodes('/FieldSet') AS T(Item)
CROSS APPLY e.column1.nodes('/FieldSet/Field') AS T2(Item2)
) column4,
(
SELECT Item2.value('(column5)[1]', 'varchar(50)')
FROM
e.column1.nodes('/FieldSet') AS T(Item)
CROSS APPLY e.column1.nodes('/FieldSet/Field') AS T2(Item2)
) column5
from @extended e
join @standard s on s.Id = e.Id
首先,您可以稍微簡化當前查詢。
select s.column1,
s.column2,
e.column1.value('(/FieldSet/Field/column4)[1]', 'varchar(50)') as column4,
e.column1.value('(/FieldSet/Field/column5)[1]', 'varchar(50)') as column5
from extended as e
join standard as s
on s.Id = e.Id
做你想做的事並不容易或快。 您需要獲取XML中所有名稱/值對的列表。
select T1.X.value('.', 'int') as Id,
T2.X.value('local-name(.)', 'sysname') as Name,
T2.X.value('.', 'varchar(10)') as Value
from extended as e
cross apply e.column1.nodes('/FieldSet/Field/id') as T1(X)
cross apply e.column1.nodes('/FieldSet/Field/*[position() > 1]') as T2(X)
在數據透視查詢中使用它並加入standard
。
select S.column1,
S.column2,
P.column4,
P.column5
from standard as s
inner join
(
select id, P.column4, P.column5
from (
select T1.X.value('.', 'int') as Id,
T2.X.value('local-name(.)', 'sysname') as Name,
T2.X.value('.', 'varchar(10)') as Value
from extended as e
cross apply e.column1.nodes('/FieldSet/Field/id') as T1(X)
cross apply e.column1.nodes('/FieldSet/Field/*[position() > 1]') as T2(X)
) as e
pivot (min(Value) for Name in (column4, column5)) P
) P
on S.Id = P.Id
要在返回動態數量的列時執行此操作,您需要動態構建此數據透視表查詢。
將名稱/值對存儲在臨時表中,使用該表來確定所需的列並構建查詢。
create table #ext
(
Id int,
Name sysname,
Value varchar(10),
primary key(Id, Name)
)
insert into #ext(Id, Name, Value)
select T1.X.value('.', 'int') as Id,
T2.X.value('local-name(.)', 'sysname') as Name,
T2.X.value('.', 'varchar(10)') as Value
from extended as e
cross apply e.column1.nodes('/FieldSet/Field/id') as T1(X)
cross apply e.column1.nodes('/FieldSet/Field/*[position() > 1]') as T2(X)
declare @SQL nvarchar(max)
set @SQL =
'select S.column1,
S.column2,
[COLLIST]
from standard as s
inner join
(
select id, [COLLIST]
from #ext as e
pivot (min(Value) for Name in ([COLLIST])) P
) P
on S.Id = P.Id'
declare @ColList nvarchar(max)
set @ColList =
(select ','+Name
from #ext
group by Name
for xml path(''), type).value('.', 'nvarchar(max)')
set @SQL = replace(@SQL, '[COLLIST]', stuff(@ColList, 1, 1, ''))
exec (@SQL)
drop table #ext
我希望它會對你有所幫助
SELECT @ COUNT_XML = 0
SELECT @COUNT_XML=(SELECT @xxxxx_GROUP_ID.value('count(/NewDataSet/position/ID)', 'INT'))
IF(@COUNT_XML > 0)
BEGIN
IF OBJECT_ID('tempdb..#TBL_TEMPOSITION') IS NOT NULL
DROP TABLE #TBL_TEMPOSITION
CREATE TABLE #TBL_TEMPOSITION (ID NUMERIC(18,0))
INSERT INTO #TBL_TEMPOSITION (ID)
SELECT XMLxxxxGroup.PositionGPItem.value('.','NUMERIC(18,0)')
FROM @xxxxx_GROUP_ID.nodes('/NewDataSet/position/ID') AS XMLPositionGroup(PositionGPItem)
SELECT @emp_cond =@emp_cond+ N' AND CM.STATIC_EMP_INFO.POSITION_ID IN (SELECT ID FROM #TBL_TEMPOSITION) '
END
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.