COALESCE() function with join - sql

I have three tables,
comments: id, user_id, place_id, text
places: id, name
users: id, name
I'd like to show a list of all the places with a list of all the users who commented on that place.
McDonalds Jill, Suzy, Bob
Walmart Fred, Joe, Suzy, Larry
Library Joe, Suzy
...
I am trying to use the coalesce function to achieve this but I am running into trouble. What am I doing wrong?
SELECT places.name, COALESCE(users.name+",")
FROM comments
JOIN places
ON comments.place_id = places.id
WHERE user_id = users.id
GROUP BY places.name
Thanks.

Try this !
Using Coalesce is not relevant here,try using STUFF with XML PATH('')
SELECT t1.name,
STUFF(
(
SELECT ',' + [places.name] FROM comments
JOIN places
ON comments.place_id = places.id
WHERE user_id = users.id
GROUP BY places.name
for xml path('')
),1,1,'') as t1 from table <group by>

Related

Join table with another table and fetch and replace the values which are ';' seperated

I am trying to join a table that has a column with data as a string and replace the values with the values from the joined table.
Tab 1
ID
Name
Categories
1
Programmer
1;2
2
Analyst
3;2
Tab 2
id
Firstname
lastname
1
john
kele
2
ajay
kashid
3
shubham
sharma
I need a query that will fetch the "Id,name and categories" from the first table but in the form like:
Id
Name
Categories
1
Programmer
john,kele ajay,kashid
2
Analyst
shubham,sharma ajay,kashid
I have written this one but this gives only the first entry, not for all the entries
SELECT
sc.Id,sc.Application,u.u_LastName + ', ' + u.u_FirstName 'coeowner '
FROM
Supportcentral AS sc
outer apply [dbo].[FN_split](sc.CoeOwner, ';',0) s
left join udcenter.dbo.[Users] u on u.u_Login COLLATE DATABASE_DEFAULT in (select s.item COLLATE DATABASE_DEFAULT)
For SQL Server 2017+, you may try the following:
SELECT T.ID, T.Name,
STRING_AGG(CONCAT(D.Firstname,' ',D.lastname),',') Categories
FROM
tab1 T JOIN tab2 D
ON D.ID IN (SELECT value FROM STRING_SPLIT(T.Categories, ';'))
GROUP BY T.ID, T.Name
ORDER BY T.ID
See a demo.
I think that you misplaced the comma in your posted output, if you want exactly the posted output use this STRING_AGG(CONCAT(D.Firstname,',',D.lastname),' ').
For older versions of SQL Server you may use for xml path to simulate the STRING_AGG function as the following:
WITH CTE AS
(
SELECT T.ID, T.Name, CONCAT(D.Firstname,' ',D.lastname) fullname FROM
tab1 T JOIN tab2 D
ON CONCAT(';', T.Categories,';') LIKE CONCAT('%;', D.ID, ';%')
)
SELECT id, name, STUFF(
(SELECT ',' + CAST(T.fullname as VARCHAR(MAX))
FROM CTE T WHERE T.ID = D.ID
FOR xml PATH ('')
), 1, 1, ''
) Categories
FROM CTE D
GROUP BY ID, Name
ORDER BY ID
See a demo.
Try this Query,
SELECT Id, Name, (SELECT STRING_AGG(Name,',') FROM #Users WHERE Id IN (SELECT Value FROM string_split(SC.Categories,';'))) AS Categories
FROM #Supportcentral SC

How can I run my SQL, to get the result such as "John Doe, plumbing"

I have table category, with id and cat_name
Example: 152, Plumbing
I have table user, with category_id and name
Example: 152, John Doe
When I do
SELECT name, category_id FROM user
As a result I will have something like
John Doe, 152
Question:
How can I run my SQL, to get the result such as
John Doe, plumbing
It is quite easy to get this, Please use below query for the same
SELECT User.Name, Category.cat_name FROM User
INNER JOIN Category ON Category.Id = User.category_id
Happy coding :-)
Try basic JOINS
SELECT C.cat_name, U.Name
FROM category C JOIN User U ON C.id = U.category_id
this will work:
select a.name,b.cat_name from user a, category b
where a.category_id=b.id
As you can understand you have two tables, and there is some 1 to 1 relationship between records of these tables(user & category).
So here we will use a simple join to connect this two table.
SELECT c.cat_name, u.name
FROM category as c, user as u
WHERE c.id = u.category_id
When I do category as c, this is called aliasing. This has two benefits. One is to keep our query short and sweet(no need to repeat category, just use c) and second is SQL query engine has 100% clarity of what we want to select.
Let's you also want to select id, then you should use c.id or u.category_id.
Check these alternate methods-
IF OBJECT_ID('Category') IS NOT NULL
DROP TABLE Category
IF OBJECT_ID('User') IS NOT NULL
DROP TABLE [User]
CREATE TABLE Category
(ID INT,Cat_name VARCHAR(20))
CREATE TABLE [User]
(Category_id INT,[Name] VARCHAR(20))
INSERT INTO Category(ID ,Cat_name)
VALUES (152,'Plumbing')
INSERT INTO [User](Category_id ,[Name])
VALUES (152,'John Doe')
--Method 1 (using CROSS APPLY)
SELECT U.[Name], C.Cat_name FROM [User] U CROSS APPLY Category C WHERE U.Category_id=C.ID
--Method 2 (using INNER JOIN)
SELECT U.[Name], C.Cat_name FROM [User] U INNER JOIN Category C ON U.Category_id=C.ID
--Method 3 (using WHERE and WITHOUT JOIN)
SELECT U.[Name], C.Cat_name FROM [User] U,Category C WHERE U.Category_id=C.ID

Duplicate GROUP_CONCAT when using JOIN

I'm creating a sort of geocache team building system and I'm having trouble with my query.
To collate and display the individuals against the teams I'm using GROUP_CONCAT, however when I try to include the locations (listed as markers) the individuals names are being duplicated based on the number of markers.
I have put together a SQL Fiddle to explain my workings.
Here is my query:
SELECT SQL_CALC_FOUND_ROWS
map_team.id AS team_id,
map_team.name,
GROUP_CONCAT(firstname, ' ', surname SEPARATOR ', ') AS full_name
FROM map_team
LEFT JOIN members
ON members.map_team=map_team.id
WHERE members.map_team IS NOT NULL
GROUP BY map_team.name
ORDER BY map_team.name ASC
Any advice would be appreciated.
GROUP_CONCAT( distinct ... ) will not give correct answers as the team member names in a team can be same. If you want to get it in a single query you can use:
SELECT SQL_CALC_FOUND_ROWS
map_team.id AS team_id,
map_team.name,
GROUP_CONCAT(firstname, ' ', surname SEPARATOR ', ') AS full_name,
(select count(*) from map_markers where team_id = map_team.id) AS total_markers,
(select count(*) from map_markers where team_id = map_team.id and status = 'completed') AS total_completed
FROM map_team
LEFT JOIN members
ON members.map_team=map_team.id
WHERE members.map_team IS NOT NULL
GROUP BY map_team.name
ORDER BY map_team.name ASC
If you don't like the idea of a subquery in select. You need to do it separately.
Use
GROUP_CONCAT(distinct firstname ...
use following query:
SELECT SQL_CALC_FOUND_ROWS
map_team.id AS team_id,
map_team.name,
GROUP_CONCAT(distinct firstname, ' ', surname SEPARATOR ', ') AS full_name,
count(*) AS total_markers,
SUM(IF(status = 'completed', 1, 0)) AS total_completed
FROM map_team
LEFT JOIN members
ON members.map_team=map_team.id
LEFT JOIN map_markers
ON map_markers.team_id=map_team.id
WHERE members.map_team IS NOT NULL
GROUP BY map_team.name
ORDER BY map_team.name ASC

duplicate answers when predicate in more than one field SQL

I'm so new to this that even the answers on questions similar to my one really don't make any sense to me (I started SQL last week)
I'm trying to list addresses from Table 1 where there are multiple in each address with the same first and surnames (i.e. John Smith and John Smith). I have first names and surnames in separate fields.
I tried
SELECT *
FROM addresses
WHERE EXISTS (
SELECT individuals.FirstName
AND individuals.Surname
FROM individuals
WHERE addresses.AddressID = individuals.AddressID
GROUP BY addresses.StreetName
HAVING COUNT( * ) >1`
but this just gives me a list of every address that has more than one person in it..
Can anyone give me a (simpleish) answer that I might get my head around.
Thanks, Stacey
If you add
individuals.FirstName, individuals.Surname
after
GROUP BY addresses.StreetName
then that should do what you want.
SELECT addresses.*
FROM addresses
INNER JOIN
(
SELECT AddressID
FROM individuals
GROUP BY AddressID, FirstName, Surname
HAVING COUNT(*) > 1
) as tbl1
ON tbl1.AddressID = addresses.AddressID
How about:
SELECT
a.*
FROM
addresses a
JOIN
individuals i
ON a.AddressID = i.AddressID
GROUP BY
a.StreetName, i.FirstName, i.Surname
HAVING
COUNT(1) > 1

SQL - Select all skills

it's been a while since I used SQL so I'm asking sorry if it's too easy.
I have to select all the skills that a user has, so I have three tables.
User (id, name)
Skills (id, name)
User_skills (id_user, id_skill)
If the user1 has 2 skills; for example Hibernate (id 1) and Java (id 2)
and the user2 has 1 skill; Java (id 1)
Passing 1 and 2, I want to retrieve users that have both.
With the IN() function I get all the users that have at least one of the skills, but I want to filter them out!
Thanks to all in advance
If one skill can only be assigned exactly once to a user (i.e. (id_user, id_skill) is the PK for the user_skills table), then the following will do what you want:
SELECT id_user
FROM user_skills
WHERE id_skill IN (1,2)
GROUP BY id_user
HAVING count(*) = 2
Join to the association table user_skills twice, putting the skill ID in the on clause of each join:
select u.*
from user u
join user_skills us1 on us1.id_user = u.id and us1.id_skill = 1
join user_skills us2 on us2.id_user = u.id and us2.id_skill = 2
By using join (and not left join) this query requires the user have both skills
SELECT name FROM user as u
WHERE
EXISTS( SELECT 1 FROM User_skills WHERE id_user=u.id AND id_skill=1 )
AND EXISTS( SELECT 1 FROM User_skills WHERE id_user=u.id AND id_skill=2 )