如何在SQL中将层次结构表转换为xml

时间:2020-07-24 10:00:22

标签: sql-server xml tsql

我需要使用t-SQL将查询结果转换为xml片段。 我的表/查询看起来像这样:

[Col1]  [Col2]      [Col3]      qty
A       group1      mod1        5
A       group1      mod2        7
A       group1      NULL        12
A       group2      mod3        8
A       group2      mod4        5
A       group2      NULL        13
A       NULL        NULL        25

,所需的XML输出应如下所示:

<A qty="25">
    <group1 qty="12">
        <mod1 qty="5"/>
        <mod2 qty="7"/>
    </group1>
    <group2 qty="13">
        <mod3 qty="8"/>
        <mod4 qty="5"/>
    </group2>
</A>

有没有一种方法可以在不旋转表和不使用动态sql的情况下实现此目的呢?

3 个答案:

答案 0 :(得分:0)

早上好,请确认这可以解决您的需求。接下来,我们可以改善性能。拥有正确的索引很重要

DDL + DML

draw_text(screen, str(score), 18, WIDTH / 2, 10)
draw_text(screen, str(int(pygame.time.get_ticks()/1000)), 18, 15, HEIGHT-20) # game timer - add this line
draw_shield_bar(screen, 5, 5, player.shield)

解决方案

DROP TABLE IF EXISTS T
GO

CREATE TABLE T(
    [Col1] VARCHAR(10),
    [Col2] VARCHAR(10),
    [Col3] VARCHAR(10),
    qty VARCHAR(10)
)
GO

INSERT T([Col1],[Col2],[Col3],qty) VALUES
('A', 'group1', 'mod1', 5 ),
('A', 'group1', 'mod2', 7 ),
('A', 'group1',  NULL , 12),
('A', 'group2', 'mod3', 8 ),
('A', 'group2', 'mod4', 5 ),
('A', 'group2', NULL  , 13),
('A',  NULL   , NULL  , 25)
GO

SELECT [Col1],[Col2],[Col3],qty 
FROM T
GO

注意!最后,我将值转换为XML,以检查结果是否合适。在生产中,没有必要执行此步骤,而这会浪费资源。

答案 1 :(得分:0)

@RonenAriely,您的解决方案启发了我。我已经对其进行了一些修改。因为我无法运行它。 我的解决方案看上去有点脏又复杂,不够优雅,但结果是正确的。

DECLARE @Tbl TABLE (Col1 CHAR(1), Col2 CHAR(6), Col3 CHAR(4), qty INT);
INSERT INTO @Tbl
VALUES ('A', 'group1', 'mod1', 5),
       ('A', 'group1', 'mod2', 7),
       ('A', 'group1', '', 12),
       ('A', 'group2', 'mod3', 8),
       ('A', 'group2', 'mod4', 5),
       ('A', 'group2', '', 13),
       ('A', '', '', 25);



WITH l1
  AS (SELECT Col1,
             Col2,
             SUM(qty) AS qty FROM @Tbl WHERE Col2 <> ''
         AND Col3 <> ''
         AND Col2 <> ''
       GROUP BY Col1,
                Col2),
  l2
  AS (SELECT Col2,
             SUM(qty) AS qty FROM @Tbl WHERE Col3 <> ''
       GROUP BY Col2),
  l3
  AS (SELECT Col2,
             Col3,
             SUM(qty) AS qty FROM @Tbl
       GROUP BY Col2,
                Col3),
  a1
  AS (SELECT Col2,
             '<' + Col3 + ' qty="' + CAST(qty AS VARCHAR(10)) + '"/>' AS c FROM l3 WHERE Col3 <> ''),

  a2
  AS (SELECT l1.Col1,
             '<' + aa.Col2 + ' qty="' + CAST(l2.qty AS VARCHAR(10)) + '">' +

             STUFF((SELECT DISTINCT '' + c FROM a1 WHERE Col2 = aa.Col2
                 FOR XML PATH ('')), 1, 0, '')
             + '</' + aa.Col2 + '>' AS c FROM a1 aa
        LEFT JOIN l1
          ON l1.Col2 = aa.Col2
        LEFT JOIN l2
          ON aa.Col2 = l2.Col2
       GROUP BY l1.Col1,
                aa.Col2,
                l2.qty)

SELECT REPLACE(REPLACE(REPLACE('<' + aa.Col1 + ' qty="' + CAST(l1.qty AS VARCHAR(10)) + '">'

    + STUFF((SELECT DISTINCT '' + c FROM a2 WHERE Col1 = aa.Col1
        FOR XML PATH ('')), 1, 0, '')
    + '</' + aa.Col1 + '>', '&amp;', '&'), '&lt;', '<'), '&gt;', '>') AS c

  FROM a2 aa
  LEFT OUTER JOIN (SELECT Col1, SUM(qty) AS qty FROM l1 GROUP BY Col1) l1
    ON l1.Col1 = aa.Col1
GROUP BY aa.Col1,
         l1.qty;

答案 2 :(得分:0)

回复我自己的帖子。

谢谢大家的帮助。最后,我已经使用动态SQL实现了一个解决方案,因为我有很多要处理的块,而且我需要一个通用的解决方案。我的最终代码如下:

DECLARE @SQL nvarchar(4000)
SELECT @SQL = 'SELECT ' + 
  STUFF((SELECT ',' + qty + ' as ''' 
         + Col1 
         + ISNULL('/'+ Col2,'') 
         + ISNULL('/'+ Col3,'') 
         + '/@qty''' FROM T ORDER BY Col1, Col2, Col3 FOR XML PATH('')) 
      ,1,1,'') + ' FOR XML PATH('''')'
EXEC(@SQL)

不幸的是,由于它需要一个物理表并且由于字符串大小的限制,它不能作为一个函数实现(这是我的最初目标)。这对于具有许多子级别的大型数据集也将不起作用。我将不得不忍受它!

相关问题