在SQL视图中的列选择中使用左联接别名

gkb*_*gkb 7 sql sql-server view

我正在努力在SQL Server中创建视图,其中的一列必须是来自不同表的逗号分隔值。例如,请考虑以下表格-

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),
)
Run Code Online (Sandbox Code Playgroud)

样本数据

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)
Run Code Online (Sandbox Code Playgroud)

我想要的是图片中显示的内容

在此处输入图片说明

虽然我可以使用下面的脚本获得结果,但我仍然认为这不是就性能而言的最佳方法(当然不是唯一的方法)-

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
Run Code Online (Sandbox Code Playgroud)

我还尝试了以下脚本来实现好运-

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
Run Code Online (Sandbox Code Playgroud)

但这不是将字符串串联在一起,也不为每种技能返回单独的行,如下所示-

在此处输入图片说明

那么,我对第一个脚本的假设正确吗?如果是这样,那么我会缺少什么概念,什么应该是实现它的最有效方法。

Yog*_*rma 5

我会尝试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);
Run Code Online (Sandbox Code Playgroud)

通过这种方式,优化程序将STUFF()不对外部查询返回的所有行调用一次。