生成xml时重复的节点

时间:2015-09-23 15:53:54

标签: sql-server xml tsql

这是我生成具有所需格式的xml的问题(我有重复的节点):我有一个表记录实体修改,可以一次在几个列上进行。例如,我有以下@my_table(我们可以看到'修改3' on'实体2'同时更改了2列,第5列和第6列):

| id_entity | id_modif  | id_column | new_value |
-------------------------------------------------    
| entity 1  | modif 1   | column 4  | coucou    |    
| entity 2  | modif 2   | column 1  | papa      |    
| entity 2  | modif 3   | column 5  | blabla    |    
| entity 2  | modif 3   | column 6  | toto      |    

我必须编写一个xml选择,它返回一个实体的所有更改。预期的xml格式如下:

<history>
  <id_entity></id_entity>
  <modifs>
    <modif>
      <id_modif></id_modif>
      <details>
        <column></column>
        <value></value>
      </details>
      <details></details>
      <details></details>
      ...
    </modif>
    <modif></modif>
    <modif></modif>
    ....
  </modifs>
</history>

示例@entity =&#39;实体1&#39; :

<history>
  <id_entity>entity 1</id_entity>
  <modifs>
    <modif>
      <id_modif>modif 1</id_modif>
      <details>
        <column>column 4</columns>
        <value>coucou</value>
      </details>
    </modif>
  </modifs>
</history>

示例@entity =&#39;实体2&#39; :

<history>
  <id_entity>entity 2</id_entity>
  <modifs>
    <modif>
      <id_modif>modif 2</id_modif>
      <details>
        <column>column 1</column>
        <value>papa</value>
      </details>
    </modif>
    <modif>
      <id_modif>modif 3</id_modif>
      <details>
        <column>column 5</column>
        <value>blabla</value>
      </details>
      <details>
        <column>column 6</column>
        <value>toto</value>
      </details>
    </modif>
  </modifs>
</history>

使用我编写的select(请参阅帖子末尾的代码),当修改更改了几列时出现问题:因为在我的表中有相同modif_id的多行,xml中的结果是重复有关节点:

-- What I Got ('modif 3' node is duplicated because in @my_table I have 2 rows with 'modif 3') :
<history>
  <id_entity>entity 2</id_entity>
  <modifs>
    <modif>
      <id_modif>modif 2</id_modif>
        <details column 1 />
    </modif>
    <modif>
      <id_modif>modif 3</id_modif>
        <details columns 5 />
        <details columns 6 />
    </modif>
    <modif>
      <id_modif>modif 3</id_modif>
        <details columns 5 />
        <details columns 6 />
    </modif>
  </modifs>
</history>

-- What I wanted (only one node 'modif 3' with 2 'details' nodes):
<history>
  <id_entity>entity 2</id_entity>
  <modifs>
    <modif>
      <id_modif>modif 2</id_modif>
        <details column 1 />
    </modif>
    <modif>
      <id_modif>modif 3</id_modif>
        <details columns 5 />
        <details columns 6 />
    </modif>
  </modifs>
</history>

我试图添加&#34; distinct&#34;在选择的声明中,但不接受。 如果您想玩...,这是完整的可运行代码:

declare @my_table table(
    id_entity varchar(10), 
    id_modif varchar(10),
    id_column varchar(15),
    new_value varchar(15))
insert into @my_table 
    select 'entity 1', 'modif 1', 'column 4', 'coucou' union
    select 'entity 2', 'modif 2', 'column 1', 'papa' union
    select 'entity 2', 'modif 3', 'column 5', 'blabla' union
    select 'entity 2', 'modif 3', 'column 6', 'toto'

declare @id_entity varchar(10) = 'entity 2'

select
    @id_entity as 'id_entity',
    (select 
        parent.id_modif as 'id_modif',
        (select distinct        
            child.id_column as 'column',
            child.new_value as 'value'
        from @my_table child
        where child.id_entity = @id_entity
        and child.id_modif = parent.id_modif
        for xml path ('details'), type ) '*'
    from @my_table parent
    where parent.id_entity = @id_entity
    for xml path ('modif'), root('modifs'), type ) '*'
    for xml path ('history'), type

注意:我找到了一个解决方法,我向我的老板展示了一个不同的xml结构,但这是一个很长的过程的结束,修改太长了......

非常感谢!

1 个答案:

答案 0 :(得分:2)

尝试gouping:

SELECT 
    t.id_entity,
    (
        SELECT 
            p.id_modif,
            (
                SELECT 
                    h.id_column,
                    h.new_value
                FROM @my_table h
                WHERE p.id_modif = h.id_modif
                FOR XML PATH('details'), TYPE
            )
        FROM @my_table AS p
        WHERE t.id_entity = p.id_entity
        GROUP BY p.id_modif
        FOR XML PATH('modif'), TYPE
    ) AS modifs
FROM @my_table AS t
WHERE t.id_entity = @id_entity
GROUP BY t.id_entity
FOR XML PATH('history'), type
相关问题