为了避免快速回复,我会提到我没有使用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调用。
有人对我有建议吗?
答案 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
。