如何在GROUP BY子句中添加XML数据类型?

时间:2011-12-23 12:52:36

标签: sql sql-server sql-server-2005 tsql

我正在创建一个论坛,所以我创建了一个包含帖子的表格。其中一个字段是Body,其类型为XML。现在我想创建一个查询,返回所有帖子和每个帖子的子节点数。我用聚合函数做这个。当我使用聚合函数时,我需要使用一个组。当我使用group by中的字段时,我会得到以下异常:

  

除非使用XML数据类型,否则无法比较或排序XML数据类型   IS NULL运算符。

我该如何解决这个问题?

我的查询是:

SELECT 
    Post.PostId, Post.[Body], Count(Children.PostId)
FROM  
    dbo.Post Post, 
    dbo.Post Children 
WHERE
    Children.ParentId = Post.PostId
GROUP BY
    Post.PostId, 
    Post.[Body]

4 个答案:

答案 0 :(得分:5)

您可以在CTE中进行聚合,然后加入

WITH Children(Cnt, ParentId)
     AS (SELECT COUNT(*),
                ParentId
         FROM   dbo.Post
         GROUP  BY ParentId)
SELECT P.PostId,
       P.[Body],
       ISNULL(Cnt, 0) AS Cnt
FROM   dbo.Post P
       LEFT JOIN Children /*To include childless posts*/
         ON Children.ParentId = P.PostId
ORDER  BY P.PostId  

答案 1 :(得分:0)

您是否可以在子查询中选择XML字段,然后选择XML字段以及在子查询上加入的其他列来进行组操作?

使用您的查询,您将获得: e.g。

SELECT Post.[Body], sq.* FROM 
(
    SELECT Post.PostId, Count(Children.PostId)
    FROM  
      dbo.Post Post, 
      dbo.Post Children 
    WHERE
      Children.ParentId = Post.PostId
    GROUP BY
      Post.PostId
) as sq
INNER JOIN Post on Post.PostId= sq.PostId

但是你在这里使用交叉连接/ ansi连接,这不是最好的方法。更好的方法是:

SELECT Post.[Body], sq.* FROM 
(
    SELECT Post.PostId, Count(Children.PostId)
    FROM  
      dbo.Post Post LEFT OUTER JOIN Children on Children.ParentId = Post.PostId
    GROUP BY
      Post.PostId
) as sq
INNER JOIN Post on Post.PostId= sq.PostId

答案 2 :(得分:0)

尝试这种方式希望它会帮助你

SELECT  Post.PostId, Post.[Body], Count(Children.PostId) over() as totalids
    FROM  
        dbo.Post Post, 
        dbo.Post Children 
    WHERE
        Children.ParentId = Post.PostId

因为我已经工作检查了这个

 create table  xmltable  (attr1 int identity ,attr2 varchar(50),attr3  xml)

    insert into xmltable select 'i',(SELECT ( SELECT 'sometext' FOR XML PATH('body'),TYPE)FOR XML PATH(''),ROOT('SampleXML')) 
    union all
     select 'j',(SELECT ( SELECT 'sometext' FOR XML PATH('body'),TYPE)FOR XML PATH(''),ROOT('SampleXML'))
     union all
     select 'k',(SELECT ( SELECT 'sometext' FOR XML PATH('body'),TYPE)FOR XML PATH(''),ROOT('SampleXML'))
    union all
    select 'l',(SELECT ( SELECT 'sometext' FOR XML PATH('body'),TYPE)FOR XML PATH(''),ROOT('SampleXML'))


create table  xmlid  (x int ,y varchar(50))
  insert into xmlid select  1,'x'
    union all
     select 1,'y'
    union all
     select 2,'z'
    union all
     select 2,'xyz1'
     union all
     select 3,'xyz2'
    union all
     select 1,'xyz3'
     select * from  xmltable
    select * from  xmlid

然后创建表

select * from  xmltable
 select * from  xmlid
 select  attr1,attr2, attr3,count(attr1) over(partition by attr2 ) as total_qtyover from  xmltable a,xmlid b
    where  a.attr1=b.x

另见How to aggregrate without using `GROUP BY`?

答案 3 :(得分:0)

我将其分解为两个查询,一个用于获取ID和子计数,另一个用于获取正文。执行GROUP BY需要服务器对分组字段进行排序,因此当您不需要时,您可能会移动并比较大量数据(除非您有多个具有相同ID的帖子实体)。 / p>