如何在SQL Server中将平面表转换为层次结构XML?

时间:2016-01-20 20:13:20

标签: sql-server xml

我有一张这样的平台:

DIV_ID  DIV_NAME MARKET_ID MARKET_NAME TRANSIT_ID TRANS_NAME 

D1     "D1 NAME"  M1        "M1 NAME"   T1       "T1 NAME"   
D1     "D1 NAME"  M1        "M1 NAME"   T2       "T2 NAME"  

想要将其转换为具有层次结构的xml,无需重复父母:

<DIVISIONS> 
<DIVISION DIV_ID="D1" DIV_NAME="D1 NAME">   
   <MARKET MARKET_ID="M1" MARKET_NAME="M1 NAME">
     <TRANSIT TRANSIT_ID="T1" TRANSIT_NAME="T1 NAME">
     <TRANSIT TRANSIT_ID="T1" TRANSIT_NAME="T1 NAME">   
    </MARKET>   
   <MARKET MARKET_ID="M2" MARKET_NAME="M2 NAME">   
   ...   
   </MARKET> 
  </DIVISION> 
<DIVISION DIV_ID="" DIV_NAME=""> 
 ... 
</DIVISION> 
</DIVISIONS>

似乎SQL可以通过使用带有一些参数的“FOR XML”直接生成它。我尝试了一些,但仍然无法得到我想要的东西。

感谢任何帮助。谢谢!

编辑:我发现了一个解决方案,但SQL Server输出'&amp; lt;'和'&amp; gt;'而不是“&lt;”,“&gt;”在嵌套元素中。这是我的代码:

SELECT DISTINCT DIV_ID AS '@DIV_ID', DIV_NAME AS '@DIV_NAME', 
  (SELECT DISTINCT MARKET_ID AS '@MARKET_ID', MARKET_NAME AS '@MARKET_NAME',
     (SELECT TRANSIT_ID AS '@TRANSIT_ID', TRANSIT_NAME AS '@TRANSIT_NAME'
     FROM HX_DIVISIONS T3
     WHERE T3.MARKET_ID = T2.MARKET_ID
     FOR XML PATH ('TRANSIT')
     ) TRANSITS
    FROM HX_DIVISIONS T2
    WHERE T2.DIV_ID = T1.DIV_ID
    FOR XML PATH ('MARKET') ) MARKETS
FROM HX_DIVISIONS T1
FOR XML PATH('DIVISION'), ROOT('DIVISIONS')

我尝试使用REPLACE(XXX,'&amp; lt;','&lt;')作为另一篇建议的帖子,但它不起作用。

输出是这样的:

<DIVISIONS>
  <DIVISION DIV_ID="D1" DIV_NAME="D1 NAME">
    <MARKETS>&lt;MARKET MARKET_ID="M1" MARKET_NAME="M1 NAME"&gt;&amp;lt;TRANSITS&gt;&lt;TRANSIT TRANSIT_ID="T1" TRANSIT_NAME="T1 NAME"/&gt;
....
</DIVISIONS>

1 个答案:

答案 0 :(得分:3)

试试这样:

DECLARE @tbl TABLE(DIV_ID VARCHAR(10), DIV_NAME VARCHAR(10), TRANSIT_ID VARCHAR(10), TRANSIT_NAME VARCHAR(10), MARKET_ID VARCHAR(10), MARKET_NAME VARCHAR(10));
INSERT INTO @tbl VALUES
 ('D1','D1 NAME','T1','T1 NAME','M1','M1 NAME')
,('D1','D1 NAME','T1','T1 NAME','M2','M2 NAME');

WITH DistinctDIVIDs AS
(
    SELECT DISTINCT DIV_ID,DIV_NAME 
    FROM @tbl
)
SELECT DIVs.DIV_ID AS [@DIV_ID]
      ,DIVs.DIV_NAME AS [@DIV_NAME]
      ,(
          SELECT markets.MARKET_ID AS [@MARKET_ID]
                ,markets.MARKET_NAME AS [@MARKET_NAME]
                ,(
                    SELECT transits.TRANSIT_ID AS [@TRANSIT_ID]
                          ,transits.TRANSIT_NAME AS [@TRANSIT_NAME]  
                    FROM @tbl AS transits
                    WHERE transits.DIV_ID=DIVs.DIV_ID AND transits.MARKET_ID=markets.MARKET_ID 
                    FOR XML PATH('TRANSIT'),TYPE
                 )
          FROM @tbl AS markets
          WHERE markets.DIV_ID=DIVs.DIV_ID
          FOR XML PATH('MARKET'),TYPE
       ) 
FROM DistinctDIVIDs AS DIVs
FOR XML PATH('DIVISION'),ROOT('DIVISIONS')

结果

<DIVISIONS>
  <DIVISION DIV_ID="D1" DIV_NAME="D1 NAME">
    <MARKET MARKET_ID="M1" MARKET_NAME="M1 NAME">
      <TRANSIT TRANSIT_ID="T1" TRANSIT_NAME="T1 NAME" />
    </MARKET>
    <MARKET MARKET_ID="M2" MARKET_NAME="M2 NAME">
      <TRANSIT TRANSIT_ID="T1" TRANSIT_NAME="T1 NAME" />
    </MARKET>
  </DIVISION>
</DIVISIONS>