我正在努力在SQL服务器中创建一个视图,其中一列需要是来自不同表的逗号分隔值。以下表为例 -
CREATE TABLE Persons
(
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR (100)
)
CREATE TABLE Skills
(
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR (100),
)
CREATE TABLE PersonSkillLinks
(
Id INT NOT NULL PRIMARY KEY,
SkillId INT FOREIGN KEY REFERENCES Skills(Id),
PersonId INT FOREIGN KEY REFERENCES Persons(Id),
)
样本数据
INSERT INTO Persons VALUES
(1, 'Peter'),
(2, 'Sam'),
(3, 'Chris')
INSERT INTO Skills VALUES
(1, 'Poetry'),
(2, 'Cooking'),
(3, 'Movies')
INSERT INTO PersonSkillLinks VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1)
我想要的是图像中显示的内容
虽然我已经能够使用下面的脚本获得结果,但我觉得这不是最好的(当然也不是唯一的)方法,就性能而言 -
CREATE VIEW vwPersonsAndTheirSkills
AS
SELECT p.Name,
ISNULL(STUFF((SELECT ', ' + s.Name FROM Skills s JOIN PersonSkillLinks psl ON s.Id = psl.SkillId WHERE psl.personId = p.Id FOR XML PATH ('')), 1, 2, ''), '') AS Skill
FROM Persons p
GO
我也试过下面的脚本运气 -
CREATE VIEW vwPersonsAndTheirSkills
AS
SELECT p.Name,
ISNULL(STUFF((SELECT ', ' + skill.Name FOR XML PATH ('')), 1, 2, ''), '') AS Skill
FROM persons p
LEFT JOIN
(
SELECT s.Name, psl.personid FROM Skills s
JOIN PersonSkillLinks psl ON s.Id = psl.SkillId
) skill ON skill.personId = p.Id
GO
但它没有连接字符串并为每个技能返回单独的行,如下所示 -
那么,我对第一个脚本的假设是正确的吗?如果是这样,我错过了什么概念,以及实现它的最有效方法。
我会尝试使用APPLY
:
SELECT p.Name, STUFF(ss.skills, 1, 2, '') AS Skill
FROM Persons p OUTER APPLY
(SELECT ', ' + s.Name
FROM Skills s JOIN
PersonSkillLinks psl
ON s.Id = psl.SkillId
WHERE psl.personId = p.Id
FOR XML PATH ('')
) ss(skills);
通过这种方式,优化器将调用STUFF()
一次不是外部查询返回的所有行。