Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Left Join Alias in Column Select in SQL Views

I am working on creating a view in SQL server one of the columns for which needs to be a comma separated value from a different table. Consider the tables below for instance -

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),
)

Sample data

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)

What I want is something like shown in the image

enter image description here

While I have been able to get the results using the script below, I have a feeling that this is not the best (and certainly not the only) way to do as far as performance goes -

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

I also tried my luck with the script below -

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

but it is not concatenating the strings and returning separate rows for each skill as shown below -

enter image description here

So, is my assumption about the first script correct? If so, what concept am I missing about it and what should be the most efficient way to achieve it.

like image 551
gkb Avatar asked Mar 26 '19 14:03

gkb


People also ask

How to use alias inside left join in SQL?

We can use AS aliases inside LEFT JOIN to make our snippet short and clean. For example, SELECT C.cat_name, P.prod_title FROM Categories1 AS C LEFT JOIN Products AS P ON C.cat_id= P.cat_id; Here, the SQL command selects common rows between Category and Products table. We can also use LEFT OUTER JOIN instead of LEFT JOIN.

How to use table aliases in SQL?

We use the "Customers" and "Orders" tables, and give them the table aliases of "c" and "o" respectively (Here we use aliases to make the SQL shorter): Aliases can be useful when: When displaying the Customers table, make an ALIAS of the PostalCode column, the column should be called Pno instead.

What is the use of left join in SQL?

The LEFT JOINis a clause of the SELECT statement. The LEFT JOINclause allows you to query datafrom multiple tables. The LEFT JOINreturns all rows from the left table and the matching rows from the right table. If no matching rows are found in the right table, NULL are used.

How do you join two tables based on common columns?

The SQL LEFT JOIN joins two tables based on a common column, and selects records that have matching values in these columns and remaining rows from the left table. SELECT Customers.customer_id, Customers.first_name, Orders.amount FROM Customers LEFT JOIN Orders ON Customers.customer_id = Orders.customer;


1 Answers

I would try with 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);

By this way, optimizer will call STUFF() once not for all rows returned by outer query.

like image 137
Yogesh Sharma Avatar answered Oct 03 '22 21:10

Yogesh Sharma