我的表有以下内容:
I Place ID
1 KARNATAKA 3
2 KARNATAKA 5
3 ANDHRA 3
4 ANDHRA 4
9 TAMILNADU 2
6 TAMILNADU 5
7 TAMILNADU 1
8 TAMILNADU 4
另一张表:
Id FirstName SecondName
1 Ram N
2 Sita K
3 Bootha MU
4 Krishnan S
5 Hari M
6 Mehta A
7 Rahul C
8 Vamsi M
9 Badri S
我正在寻找以下输出:
Place FirstName
KARNATAKA Bootha, Hari
ANDHRA Bootha, Krishnan
同样是第三排。
基本上,它在第二列中结合了“STUFFS”。
我尝试下面的查询,但它不起作用。
select ad.Place, STUFF((SELECT ', '+ FirstName FROM Associate a INNER JOIN Address Ad on a.Id = Ad.ID
FOR XML PATH ('')) , 1, 1, '')
From Address ad inner join Associate a
on ad.ID = a.Id
group by ad.Place
只需稍加修正,请帮帮我?
答案 0 :(得分:3)
问题是你有太多的联接。这很棘手,因为两个表之间的连接是id
,但是您在不同级别进行聚合。因此,在子查询中确实需要join
和相关条件:
select ad.Place,
STUFF((SELECT ', ' + a.FirstName
FROM Associate a join
Address ad2
on a.Id = ad2.Id
WHERE ad2.Place = ad.Place
FOR XML PATH ('')
) , 1, 2, '')
From Address ad
group by ad.Place;
作为次要问题,您对stuff()
(1, 1
)的参数会在连接字符串的开头留一个空格。
答案 1 :(得分:0)
首先,我建议您规范化数据库架构。实际上,您在存储地名的第一个表中有一些冗余。我建议你在一个表中记录位置,在另一个表中记录人物,在单独的N:N链接表中记录人物和地点之间的关系:
CREATE TABLE Place
(
Id INT NOT NULL PRIMARY KEY,
Name NVARCHAR(50) NOT NULL
);
CREATE TABLE Person
(
Id INT NOT NULL PRIMARY KEY,
Name NVARCHAR(50) NOT NULL
);
CREATE TABLE PersonAtPlace
(
PersonId INT NOT NULL REFERENCES Person (Id),
PlaceId INT NOT NULL REFERENCES Place (Id),
PRIMARY KEY (PersonId, PlaceId)
);
现在针对按地点汇总人员的问题,您实际上并不需要GROUP BY
子句。试试这个:
SELECT pl.Name,
COALESCE(STUFF((SELECT DISTINCT ', ' + pn.Name
FROM PersonAtPlace plXpn
INNER JOIN Person pn ON pn.Id = plXpn.PersonId
WHERE plXpn.PlaceId = pl.Id
ORDER BY ', ' + pn.Name -- this is optional
FOR XML PATH('')), 1, 1, ''), '') AS People
FROM Place pl;
以下是有关如何阅读此查询的一些指导:
外部SELECT
的唯一目的是为每个地方生成一行(因为您正在为每个地方创建一个摘要 ),并且可以引用它放在内部查询中。
内部查询执行人员摘要(通过将其名称连接成以逗号分隔的列表字符串)。
WHERE
子句,我们会过滤掉所有不属于我们当前正在总结的地方的记录(即pl
来自外部SELECT
)。< / LI>
JOIN
才能找到某个人的姓名。GROUP BY
是可选的,但如果存在,则确保对逗号分隔列表中的名称进行排序。STUFF … FOR XML PATH
的作用:将名称连接成以逗号分隔的列表字符串。