【问题标题】:T-SQL: How to select rows as XML elementT-SQL:如何选择行作为 XML 元素
【发布时间】:2016-01-07 17:32:49
【问题描述】:

我有桌子

   Cost       RenderedValue    SectionName
   ------------------------------------
  100.00      1000.00          Section1
  200.00      2000.00          Section2
  300.00      3000.00          Section3
  400.00      4000.00          Section4

我想生成这个 XML:

<Root>
   <Section1Cost>100.00</Section1Cost>
   <Section1RenderedValue>1000.00</Section1RenderedValue>
   <Section2Cost>200.00</Section2Cost>
   <Section2RendredValue>2000.00</Section2RendredValue>
</Root>

我能够使用 TSQL 生成它(Test 是我的表名)

SELECT
    (SELECT Cost AS 'Cost'FROM Test WHERE SectionName = 'Section1') AS 'Section1Cost',
    (SELECT RenderedValue AS 'Cost'FROM Test WHERE SectionName = 'Section1') AS 'Section1RenderedValue',
    (SELECT Cost AS 'Cost'FROM Test WHERE SectionName = 'Section2') AS 'Section2Cost',
    (SELECT RenderedValue AS 'Cost'FROM Test WHERE SectionName = 'Section2') AS 'Section2RendredValue'
FOR XML Path(''), Root('Root')

但这很丑,我认为它没有优化。它可以更优雅还是我拥有的任何东西都是正确的?

我在那个测试表中最多可以有 30 行

【问题讨论】:

  • 请注意,所有在 SO 上提供答案的专业人士都渴望获得声誉积分。 Please read this: someone-answers。也可以看看您的旧问题。谢谢!

标签: sql-server xml tsql for-xml


【解决方案1】:

这为您提供了稍微不同的 XML(使用 Section 标记),但 SQL 脚本应该更有效:

SELECT
    Test.SectionName AS [@SectionName],
    Test.Cost AS [Cost],
    Test.RenderedValue AS [RenderedValue]

FROM Test
ORDER BY Test.SectionName
FOR XML PATH ('Section'), ROOT('Sections');

这是您提供的示例表的该脚本的输出:

<Sections><Section SectionName="Section1"><Cost>100.0000</Cost><RenderedValue>1000.0000</RenderedValue></Section><Section SectionName="Section2"><Cost>200.0000</Cost><RenderedValue>2000.0000</RenderedValue></Section><Section SectionName="Section3"><Cost>300.0000</Cost><RenderedValue>3000.0000</RenderedValue></Section><Section SectionName="Section4"><Cost>400.0000</Cost><RenderedValue>4000.0000</RenderedValue></Section></Sections>

【讨论】:

  • 不,这不是我要找的。我无法更改 xml 的结构。
【解决方案2】:

我想我明白了

EDIT1

我想收回我所说的话,我提到的解决方案并不完全按照我想要的方式工作。当记录不存在时,我想打印 0。所以如果修改上面的内容它不起作用

 select 
 case when t.sectionname = 'section1' then t.cost else 0 end as 'section1cost',
 case when t.sectionname = 'section1' then t.renderedvalue else 0 end as 'section1rendervalue'
 from test t
 for xml path(''),root('root')

【讨论】:

  • 但这不会为您动态命名 XML 标记,如 section1、section2 等,还是不需要?
  • no xml 元素是固定的,元素名称基于部分名称
  • 感谢您的评论。我想我有你需要的确切解决方案。查看我的最新答案。
【解决方案3】:

您好,这里是根据您的最新回答 user3862378 修改的我之前回答的版本

DECLARE @sql varchar(max) = ''
DECLARE @case VARCHAR(MAX) = ''

SELECT  @case += 'case when t.sectionname = '''+SectionName+''' then t.cost  end as '''+SectionName+'Cost'',
 case when t.sectionname = '''+SectionName+''' then t.renderedvalue  end as '''+SectionName+'RenderedValue'','

  FROM <YOUR TABLE NAME>

  SELECT @sql = 'select '+ SUBSTRING(@case,1,LEN(@case)-1) +'from <YOUR TABLE NAME> t
 for xml path(''''),root(''root'')'

 EXECUTE (@sql)

结果如下:

<root>
  <Section1Cost>100.00</Section1Cost>
  <Section1RenderedValue>1000.00</Section1RenderedValue>
  <Section2Cost>200.00</Section2Cost>
  <Section2RenderedValue>2000.00</Section2RenderedValue>
  <Section3Cost>300.00</Section3Cost>
  <Section3RenderedValue>3000.00</Section3RenderedValue>
  <Section4Cost>400.00</Section4Cost>
  <Section4RenderedValue>4000.00</Section4RenderedValue>
</root>

【讨论】:

  • 这应该动态创建每个元素,其名称基于 SectionName 列中的值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 2017-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多