如何在select语句中执行多个聚合列

时间:2010-01-22 19:57:32

标签: sql sql-server

为了避免快速回复,我会提到我没有使用MySQL,所以我不能使用GROUP_CONCAT,而且我也已经查看了this question

示例
(这不是我正在使用的数据,但它准确地描述了我的情况)
人员表,ID,名称列
Person_Countries访问表,具有PersonID,Country列(1..M链接表)
Person_StatesVisited表,具有PersonID,State列(1..M链接表)

约束
我无法修改数据库。我也无法修改大部分代码,所以这必须在SQL中完成,而不是在运行查询后在代码中完成。

期望的结果
带有列的结果集
Person.ID,
Person.Name,
[相关Person_CountriesVisited.Country列表],
[相关Person_StatesVisited.State列表],

也可以通过适用于所有列的通用搜索词进行过滤。

我的尝试

现在,我的SQL-fu现在并不是那么尖锐,但我正在根据我发现的例子做我能做的事情。

1)我尝试过使用标量子查询:

  

SELECT P.ID,P.Name,
(选择   CV.Country +','从FROM   Person_CountriesVisited CV ON P.ID =   CV.PersonId
FOR FOR XML PATH(''))AS   CountriesVisited,
(SELECT   SV.State +','
FROM   Person_States访问SV ON P.ID =   SV.PersonId
FOR FOR XML PATH(''))AS StatesVisited

  来自人物P

在哪里P.Name LIKE   '%'+ @ SearchTerm +'%'左或   CountriesVisited LIKE'%'+   @SearchTerm +'%'
或StatesVisted   喜欢'%'+ @ SearchTerm +'%'

返回我想要的数据,但仅在我删除WHERE子句时。它不适用于WHERE子句,因为SQL Server 2005似乎不喜欢我在WHERE子句中引用从标量子查询创建的列。它给了我一个“无效的列名'CountriesVisited'”错误(同样是StatesVisited列)。

2)我尝试了交叉应用技巧:

  

SELECT P.ID,P.Name,CountriesVisited,   访问对象

来自人P
  INNER JOIN Person_Countries访问CV ON   P.ID = CV.PersonID
交叉申请   (
选择CV.Country +','
  来自人P2 INNER JOIN   Person_CountriesVisited CV ON P2.ID =   CV.PersonID
WHERE P.ID =   P2.ID
用于XML路径('')
)   PRE_TRIMMED(CountriesVisited)
  
  INNER JOIN Person_States访问SV ON   P.ID = SV.PersonID
  交叉申请(
选择SV.State +   ',''来自人P2 INNER JOIN   Person_States访问SV ON P2.ID =   SV.PersonID for XML PATH('')
)   PRE_TRIMMED(StatesVisited)

在哪里   P.Name LIKE'%'+ @ SearchTerm +   '%'或者CountriesVisited LIKE'%'   + @SearchTerm +'%'
或StatesVisted LIKE'%'+ @ SearchTerm +   '%'

但这不起作用,因为你显然不能有多个pre_trimmed调用。

有人对我有建议吗?

1 个答案:

答案 0 :(得分:3)

您只需要对子查询进行别名:

WITH x AS (
  SELECT P.ID
        ,P.Name
        ,( select CV.Country + ', '
         FROM Person_CountriesVisited CV ON P.ID = CV.PersonId 
         FOR XML PATH ('')
        ) AS CountriesVisited
        ,( SELECT SV.State + ', '
         FROM Person_StatesVisited SV ON P.ID = SV.PersonId 
         FOR XML PATH ('')
        ) AS StatesVisited
  FROM Person P
)
SELECT *
FROM X    
WHERE Name LIKE '%' + @SearchTerm + '%'
  OR CountriesVisited LIKE '%' + @SearchTerm + '%'
  OR StatesVisted LIKE '%' + @SearchTerm + '%'

你可以在第二个例子中做类似的事情。实际上在第二个例子中,只是将第二个子查询别名为新的,如PRE_TRIMMED2