6

我的架构中有几个多对多关系。例如,一个包有许多任务组,而任务组又具有许多任务。所有表通过多对多表链接在一起,例如包含包的主键和任务组的主键。(我知道这不是严格需要的,因为 XML 是一对多的,但我想不出更好的结构)。

是否可以将查询结果作为 XML 获取,反映一对多的结构?所以,结果应该是这样的:

<package id=1>
  <taskgroup id=1>
    <task id=1>
    <task id=2>
  </taskgroup>
  <taskgroup id=2>
    <task id=3>
  </taskgroup>
</package>

XMLELEMENT()通过使用andXMLATTRIBUTE()函数来完成所有任务,我已经设法获得了我想要的部分内容。像这样:

    SELECT XMLELEMENT(name task,
      XMLATTRIBUTES(p.name as packageName),
        XMLELEMENT(name description, t.description),
        XMLELEMENT(name tutorial,
          XMLELEMENT(name someTaskChild1, t.data1)),
        XMLELEMENT(name objectives,
          XMLELEMENT(name someTaskChild2, t.data2)),
    ) 
    FROM packages p
    INNER JOIN package_taskgroup pt ON p.id = pt.package_id
    INNER JOIN taskgroups tg on pt.taskgroup_id = tg.id
    INNER JOIN taskgroup_task tt on tg.id = tt.taskgroup_id
    INNER JOIN tasks t on tt.task_id = t.id
    WHERE p.id = somePackageId AND tg.id = someTaskGroupId

问题是如何将这些任务分组到它们的父表元素中?

4

2 回答 2

7

尝试:

SELECT p.id as pack_id,
       XMLELEMENT(name taskgroup,
                  XMLATTRIBUTES(tg.id as id),
                  XMLAGG(XMLELEMENT(name task,
                         XMLATTRIBUTES(t.id as id)) as xml_task_group
FROM packages p
JOIN package_taskgroup pt ON p.id = pt.package_id
JOIN taskgroups tg on pt.taskgroup_id = tg.id
JOIN taskgroup_task tt on tg.id = tt.taskgroup_id
JOIN tasks t on tt.task_id = t.id
WHERE p.id = somePackageId 
GROUP BY p.id, tg.id

这将为您提供p.id您指定的所有任务组。

然后:

SELECT XMLELEMENT(name package, 
                  XMLATTRIBUTES(pack_id as id),
                  XMLAGG(xml_task_group))
FROM (previous SELECT here)

这将为您提供您指定的结构。

详细信息:XMLAGG , XML 函数

加入的选择将如下所示:

SELECT XMLELEMENT(name package, 
                  XMLATTRIBUTES(pack_id as id),
                  XMLAGG(xml_task_group))
FROM (SELECT p.id as pack_id,
             XMLELEMENT(name taskgroup,
                        XMLATTRIBUTES(tg.id as id),
                        XMLAGG(XMLELEMENT(name task,
                                          XMLATTRIBUTES(t.id as id)
                       ))) as xml_task_group
      FROM packages p
      JOIN package_taskgroup pt ON p.id = pt.package_id
      JOIN taskgroups tg on pt.taskgroup_id = tg.id
      JOIN taskgroup_task tt on tg.id = tt.taskgroup_id
      JOIN tasks t on tt.task_id = t.id
      WHERE p.id = somePackageId 
      GROUP BY p.id, tg.id) t
GROUP BY pack_id

我只是将第一个选择复制到FROM第二个的子句中。

于 2012-12-21T10:29:49.907 回答
0

你可以这样尝试:

SELECT 
     T0."Mail",
     T0."UserName", 
     (SELECT xmlagg(xmlelement(name Screens, 
                               XMLELEMENT(name "IN1_ID","IN1."ID"),
                               XMLELEMENT(name "IN1_Name", IN1."Name")
                              )
                    ) 
             FROM "Advertisement"."Screen" IN1 
             WHERE T0."ID" = IN1."PlatformID"
    ) AS Screens 
    FROM "Sales"."Platform" T0

XNL 输出将如下所示:

<screens>
   <IN1_PlatformID>14</IN1_PlatformID>
   <IN1_Name>My Name</IN1_Name>
</screens>
<screens>
   <IN1_PlatformID>15</IN1_PlatformID>
   <IN1_Name>My Name 2</IN1_Name>
</screens>

在 c# 端,您需要插入一个根节点来读取它。

var doc = new System.Xml.XmlDocument();
doc.LoadXml("<rows>" + row["Screens"].ToString() + "</rows>");

之后,您可以转换为数据集以轻松读取屏幕数据:

var xmlReader = new System.Xml.XmlNodeReader(doc);
var dataSet = new System.Data.DataSet();
dataSet.ReadXml(xmlReader);
foreach (System.Data.DataRow item in dataSet.Tables[0].Rows){
    ...
}
于 2016-08-19T09:18:04.690 回答