sql-server 生成xml时出现重复节点

cyvaqqii  于 2022-10-31  发布在  其他
关注(0)|答案(1)|浏览(159)

下面是我生成所需格式的xml时遇到的问题(我有重复的节点):我有一个记录实体修改的表,可以一次对多个列进行修改。例如,我有以下@my_table(我们可以看到'entity 2'上的'modify 3'同时更改了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 select,它返回其中一个实体的所有更改。预期的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 =“实体1”示例:

<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 =“实体2”示例:

<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(请参见文章末尾的代码),当修改更改了几列时,问题就出现了:因为在我的表中,对于相同的modify_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>

我试着在select语句中添加“distinct”,但它没有被接受。如果你想玩......以下是完整的可运行代码:

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结构,但这是一个非常长的过程的结束,这将是太长的修改...。
多谢了!

okxuctiv

okxuctiv1#

试组平:

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

相关问题