2016-05-31 61 views
2

我想通過XML列進行迭代,並生成以下報告遍歷在SQL Server中的XML列

表EmpTransaction結構

EmployeeId  TransactionFieldDetails 
458    <PayDetails>...</PayDetails> 
459    <PayDetails>...</PayDetails> 

下面是XML結構

<PayDetails> 
    <Column Name="NETPAY" DataType="float" Value="45112" /> 
    <Column Name="TDS" DataType="float" Value="150000" /> 
</PayDetails> 

所需的輸出

EmployeeId  FieldName Value 
458    NETPAY 45112 
458    TDS  15000 
459    NETPAY 45236 
459    TDS  17000 

我曾試圖實現上述使用不是Temptable 報告要求單查詢才達到上述報告

我試着用以下解決方法來實現

create table #EMPXML (employeeId int, fldname varchar(max),fldval varchar(max)) 
select ROW_NUMBER()OVER(ORDER BY EmployeeId)AS ID ,EmployeeId,TransactionFieldDetails into #MKISQS_XML from dbo.EmpTrans 

DECLARE @TOTINQ INT = (select COUNT(DISTINCT EmployeeId) from #MKISQS_XML) 
DECLARE @INQCNT INT = 1 
DECLARE @INQCODE VARCHAR(10) 
DECLARE @INQXML XML 
DECLARE @RELATEDTO VARCHAR(15) 
WHILE(@TOTINQ >[email protected]) 
BEGIN 
    SET @INQCODE = (SELECT EmployeeId FROM #MKISQS_XML WHERE [email protected]) 
    SET @INQXML = (SELECT TransactionFieldDetails FROM #MKISQS_XML WHERE [email protected]) 

    INSERT INTO #EMPXML 
    SELECT @INQCODE,    
      T.c.value('(@Name)[1]', 'Varchar(max)') AS fldname, 
      T.c.value('(@Value)[1]', 'Varchar(max)') AS fldval 
    FROM @INQXML.nodes('//PayDetails/Column') T(c) 
    SET @INQCNT = @INQCNT+1 
END 

select * from #EMPXML 

需要知道可以在上面查詢可以被簡化,而不是建立臨時表

回答

3

你可以用一個簡單的交叉應用。

CREATE TABLE #tXML (
    EmployeeId int, 
    TransactionFieldDetails XML 
); 

insert into #tXML 
(EmployeeId, TransactionFieldDetails) 
values 
(458,'<PayDetails><Column Name="NETPAY" DataType="float" Value="45112" /><Column Name="TDS" DataType="float" Value="150000" /></PayDetails>'), 
(459,'<PayDetails><Column Name="NETPAY" DataType="float" Value="45236" /><Column Name="TDS" DataType="float" Value="17000" /></PayDetails>'); 


select 
    T.EmployeeId, 
    X.[FieldName], 
    X.[Value] 
from #tXML T 
cross apply (
SELECT   
      T.c.value('@Name', 'Varchar(max)') AS [FieldName], 
      T.c.value('@Value', 'Varchar(max)') AS [Value] 
FROM TransactionFieldDetails.nodes('/PayDetails/Column') T (c) 
) X; 

DROP TABLE #tXML; 
+0

好的答案,+1從我身邊...您可能會簡化這一點:儘可能具體,因此在這裏沒有雙斜線:'//PayDetails'.This是根節點,使用'/PayDetails ...'...並且不需要爲單身人員強制使用屬性。 'T.c.value('@ Name',...'就夠了... – Shnugo

+0

@Shnugo Thx的建議。編輯。 – mxix