有没有比在SQL中使用FOR XML更好的选择

时间:2014-06-16 10:23:05

标签: sql sql-server

我遇到Sub查询时遇到问题,当我在表中有很多记录时,我的SQL速度下降了很多。我只是想知道a)我是否正确地做了或b)还有另一种做我想做的事情。

[人物]

ID  |  Name
------------
 1  |   Bob      
 2  |  Tom

[宠物]

ID  |  Category
----------------
 1  |    Cats
 2  |    Dogs
 3  |    Snakes

[PeoplePets]

PeopleID  |  PetID
-------------------
   1      |    2
   1      |    3
   2      |    1
   2      |    2

QUERY

Select Name,
STUFF((SELECT ', ' + Category FROM PeoplePets PP 
INNER JOIN Pets P ON P.ID=PP.PetID FOR XML PATH('')), 1, 2, '') AS PersonsPets
FROM People

RESULT

Name   |  PersonsPets
---------------------
 Bob   |   Dogs, Snakes
 Tom   |   Cats, Dogs

好的,这是我所拥有的非常简化的版本,但我想知道这是最好还是唯一的方法呢?

对于一个表我有大约30000个记录,当我返回前300个时,只需要一个Sub查询就可能需要大约3秒,当我添加更多Sub查询时它会变得更慢。所以从本质上讲,我只是尝试对类别进行分组(最多可以有10个不同的类别)并从数据中创建一个列。

1 个答案:

答案 0 :(得分:2)

函数stuff()不会减慢您的查询速度。子查询正在减慢速度。

这是您的查询:

Select Name,
       STUFF((SELECT ', ' + Category
              FROM PeoplePets PP  INNER JOIN
                   Pets P
                   ON P.ID = PP.PetID
              FOR XML PATH('')
             ), 1, 2, ''
            ) AS PersonsPets
FROM People;

我看不到外部查询的相关性,所以我认为它做了很多工作 - 并在每一行上生成相同的列表。你应该先尝试这样的事情:

Select Name,
       STUFF((SELECT ', ' + Category
              FROM PeoplePets PP  INNER JOIN
                   Pets P
                   ON P.ID = PP.PetID
              WHERE People.ID = PP.PeopleID
              FOR XML PATH('')
             ), 1, 2, ''
            ) AS PersonsPets
FROM People;

其次,您应该确保所有id列都已编入索引,以及PeoplePets(PeopleId, PetId)