如何在SQL中控制XML的输出格式

时间:2013-12-02 18:59:36

标签: sql sql-server xml sql-server-2008-r2 for-xml

我正在尝试以XML格式从(SQL Server 2008 R2)表中检索数据,但似乎无法将其转换为理想的结构。我尝试了各种FOR XML模式和连接方法,但是我对XML的经验很少,并且在此之前没有通过SQL使用XML输出。

我的数据位于名为XMLResults的表中,其结构如下:

ResultID    Country Product Disposition Results
-----------------------------------------------
1           UK      ABC     Result1     100
2           UK      ABC     Result2     200
3           UK      ABC     Result3     300
4           UK      XYZ     Result1     100
5           UK      XYZ     Result2     200
6           UK      XYZ     Result3     300
7           USA     ABC     Result1     100
8           USA     ABC     Result2     200
9           USA     ABC     Result3     300
10          USA     XYZ     Result1     100
11          USA     XYZ     Result2     200
12          USA     XYZ     Result3     300

目前我有这个问题:

SELECT (SELECT Country,
                (SELECT Product,
                        (SELECT Disposition, Results
                           FROM XMLResults t1
                          WHERE t1.ResultID = t2.ResultID
                            FOR XML PATH ('Dispositions'), TYPE, ELEMENTS
                        )
                   FROM XMLResults t2
                  WHERE t2.ResultID = t3.ResultID
                    FOR XML PATH ('Products'), TYPE, ELEMENTS
                )
          FROM XMLResults t3
         ORDER BY Country, Product
           FOR XML PATH ('Countries'), TYPE, ELEMENTS
        )
   FOR XML PATH('Stats');

返回XML如下:

<Stats>
  <Countries>
    <Country>UK</Country>
    <Products>
      <Product>ABC</Product>
      <Dispositions>
        <Disposition>Result1</Disposition>
        <Results>100</Results>
      </Dispositions>
    </Products>
  </Countries>
  <Countries>
    <Country>UK</Country>
    <Products>
      <Product>ABC</Product>
      <Dispositions>
        <Disposition>Result2</Disposition>
        <Results>200</Results>
      </Dispositions>
    </Products>
  </Countries>
  <Countries>
    <Country>UK</Country>
    <Products>
      <Product>ABC</Product>
      <Dispositions>
        <Disposition>Result3</Disposition>
        <Results>300</Results>
      </Dispositions>
    </Products>
  </Countries>
  ...
</Stats>

并不可怕,但我希望它不会在每次结果后一直退回到“国家”级别,也可能不需要额外的通用标签。

这样的事情会更好:

<Stats>
  <Countries>
    <Country = "UK">
      <Products>
        <Product = "ABC">
          <Dispositions>
            <Disposition>
              <ReasonCode>Result1</ReasonCode>
              <Count>100</Count>
            </Disposition>
            <Disposition>
              <ReasonCode>Result2</ReasonCode>
              <Count>200</Count>
            </Disposition>
            <Disposition>
              <ReasonCode>Result3</ReasonCode>
              <Count>300</Count>
            </Disposition>
          </Dispositions>
        </Product>
        ...
      </Products>
    </Country>
    ...
  </Countries>
</Stats>

甚至可能是这样的东西(看起来有点干净):

<Stats>
  <Country = "UK">
    <Product = "ABC">
      <Disposition ReasonCode = "Result1" Count = "100" />
      <Disposition ReasonCode = "Result2" Count = "200" />
      <Disposition ReasonCode = "Result3" Count = "300" />
    </Product>
    <Product = "XYZ">
      <Disposition ReasonCode = "Result1" Count = "100" />
      <Disposition ReasonCode = "Result2" Count = "200" />
      <Disposition ReasonCode = "Result3" Count = "300" />
    </Product>
  </Country>
  <Country = "USA">
    <Product = "ABC">
      <Disposition ReasonCode = "Result1" Count = "100" />
      <Disposition ReasonCode = "Result2" Count = "200" />
      <Disposition ReasonCode = "Result3" Count = "300" />
    </Product>
    <Product = "XYZ">
      <Disposition ReasonCode = "Result1" Count = "100" />
      <Disposition ReasonCode = "Result2" Count = "200" />
      <Disposition ReasonCode = "Result3" Count = "300" />
    </Product>
  </Country>
</Stats>

输出格式不是一成不变的,所以如果有建议,我也会对此提出建议。

谢谢, 肖恩


编辑样本数据:

CREATE TABLE XMLResults (
      ResultID BIGINT IDENTITY(1,1) NOT NULL
    , Country VARCHAR(50) NOT NULL
    , Product VARCHAR(50) NOT NULL
    , Disposition VARCHAR(50) NOT NULL
    , Results INT NOT NULL);

INSERT INTO XMLResults (Country, Product, Disposition, Results)
VALUES ('UK',  'ABC', 'Result1', 100)
     , ('UK',  'ABC', 'Result2', 200)
     , ('UK',  'ABC', 'Result3', 300)
     , ('UK',  'XYZ', 'Result1', 100)
     , ('UK',  'XYZ', 'Result2', 200)
     , ('UK',  'XYZ', 'Result3', 300)
     , ('USA', 'ABC', 'Result1', 100)
     , ('USA', 'ABC', 'Result2', 200)
     , ('USA', 'ABC', 'Result3', 300)
     , ('USA', 'XYZ', 'Result1', 100)
     , ('USA', 'XYZ', 'Result2', 200)
     , ('USA', 'XYZ', 'Result3', 300);

1 个答案:

答案 0 :(得分:1)

如果您想要以属性为中心的xml,请在列别名前添加“@”。您可以完全自定义输出,例如:

SELECT
  Country [@Country],
  (SELECT
    Product [@Product],
    (SELECT
      Disposition [@ReasonCode],
      Results [@Count]
    FROM #XMLResults t3
    WHERE t3.Country = t1.Country AND t3.Product = t2.Product
    FOR XML PATH('Disposition'),TYPE)
  FROM #XMLResults  t2
  WHERE t2.Country = t1.Country
  GROUP BY Product
  FOR XML PATH('Product'),TYPE)
FROM #XMLResults  t1
GROUP BY Country
FOR XML PATH('Country'), ROOT ('Stats')

只是玩弄它。