【问题标题】:How to control the output format of XML in SQLSQL中如何控制XML的输出格式
【发布时间】:2013-12-02 18:59:36
【问题描述】:

我正在尝试从 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);

【问题讨论】:

  • 设置SQL Fiddle 来创建表格并将一些示例数据插入其中会非常有帮助....

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


【解决方案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')

随便玩玩吧。

【讨论】:

  • 这很好,只是它通过该产品的处置数量复制了产品部分。在样本数据中,每个产品有 3 个结果,因此每个国家/地区的每个产品显示 3 次(而不是 3 个结果只显示一次)。有没有解决的办法?我还没有找到解决办法。
  • 答案已更改以符合要求。我为 t2 添加了 GROUP BY 产品
猜你喜欢
  • 1970-01-01
  • 2010-12-08
  • 2021-12-02
  • 1970-01-01
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
相关资源
最近更新 更多