Create 2 new columns from a query - sql

I am battling with joins and inner joins.
I have 2 tables that look like this:
USERS
-----------------------------------------
ID | fname | lname | div_1_id | div_2_id
-----------------------------------------
1 paul smith 1 2
2 john lip 2 null
3 kim long 1 4
DIVISIONS
------------------
ID | name
------------------
1 estate
2 litigation
3 property
4 civil
DESIRED RESULT (sql query)
--------------------------------------------------
user.ID | fname | lname | div_1_name | div_2_name
--------------------------------------------------
1 paul smith estate litigation
2 john lip litigation
3 kim long estate civil
I would like to create a new table from a MS sql query that looks like the above.

Use LEFT JOIN for this:
SELECT u.ID, u.fname, u.lname
, d1.name as div_1_name
, d2.name as div_2_name
FROM USERS u
LEFT JOIN DIVISIONS d1 ON u.div_1_id = d1.ID
LEFT JOIN DIVISIONS d2 ON u.div_2_id = d2.ID
See this SQLFiddle

Try using sub-query:
select a.ID, a.fname, a.lname,
(select name from DIVISIONS b where b.id=a.div_1_id) div_1_name,
(select name from DIVISIONS b where b.id=a.div_2_id) div_2_name
from
USERS a

Use INNER JOIN
SELECT Users.ID, Users.fname, Users.lname, Divisions.name,Div.name
FROM Users INNER JOIN Divisions ON Users.div_id_1 = Divisions.ID
INNER JOIN Divisions Div ON Users.div_id_1 = Div.ID -- Second join with Divisions Table with Alias.

Related

SQL query Postgres 12

I'm doing an inner join on a table like this:
SELECT *
FROM patient p
INNER JOIN
vaccine v
ON
p.vaccine_id = v.id
The condition f.vac_1 = mv.id might not been satisfied in the case where a person have not been vaccinated. In such case, I don't want to ignore the row, but instead of displaying the vaccine name (which is the purpose of the inner join) to display an emtpy string.
How can this be done ?
Example
Table vaccinne
id
name
1
Moderna
2
Comirnaty
3
Janssen
Table patient
id
name
vaccine_id
1
john
1
2
kermit
2
3
jessica
I'm looking for a query to produce:
id
name
vaccine_id
1
john
Moderna
2
kermit
Comirnaty
3
jessica
If I understand correctly, you want a left join starting with foo:
SELECT *
FROM foo f LEFT JOIN
vac v
ON f.vac_1 = mv.id

Sql query , grouping result from left outer join to a single cell/field of main table

Let's say that i have the following 3 tables :
IDUser Name Surname
1 Lucas Wurth
2 John Charson
3 Erik Drown
IDUser IDLocation
1 1
1 2
2 1
3 2
IDLocation Name
1 Rome
2 Milan
a User Table , a Location table , and a table to assign a location to our users.
I'd like to extract from my database all the users and have a specific column where all assigned locations are reported like so:
IDUser Name Surname Locations
1 Lucas Wurth Rome - Milan
2 John Charson Rome
3 Erik Drown Milan
Note that the user 1 has both Rome & Milan assigned
Currently my query:
SELECT
U.IDUser,
U.Name,
U.Surname,
UL.Name AS LocationName
FROM Users U
LEFT OUTER JOIN UserLocation UL ON
UL.IDUser = U.IDUser
LEFT OUTER JOIN Location L ON
UL.IDLocation = L.IDLocation
Is obviously returning a total of 4 records instead of 3 , is it possible to achievie this using the aggregate function group by? and if so how should i do this?
If you are using SqlServer you can use STRING_AGG :
SELECT
U.IDUser,
U.Name,
U.Surname,
STRING_AGG(UL.Name, ' - ') AS Locations
FROM Users U
LEFT OUTER JOIN UserLocation UL
ON UL.IDUser = U.IDUser
LEFT OUTER JOIN Location L
ON UL.IDLocation = L.IDLocation
GROUP BY U.IDUser, U.Name, U.Surname

Double outer Join

I have table A that looks like this
ID AValue
----------------------
3 Tom
5 John
9 Mike
and table B that looks like this
ID BValue
----------------------
2 Nancy
3 Maria
9 Clara
10 Sophia
I am trying to join both tables to get this result
ID AValue BValue
------------------------------
2 <NULL> Nancy
3 Tom Maria
5 John <NULL>
9 Mike Clara
10 <NULL> Sophia
If i try to left outer join I would miss the records that do not have match in A
and If I try the right outer join i would miss the records that do not have match in B
any other way I can use?
what you need is FULL OUTER JOIN
SELECT ID = coalesce(a.ID, b.ID), AValue, BVlaue
FROM TalbleA a FULL OUTER JOIN TableB b
ON a.ID = b.ID

Condition with INNER JOIN gives wrong results

I have the following tables
goal matches team_match
id | match_id | team_id | name match_id team_id | match_id | home_away
----------------------------- ----- ------------------------------
1 1 1 Ronaldo 1 1 1 home
2 1 2 Messi 2 1 away
3 1 2 Suarez 2 1 away
Now I want to get just players who played in the away team.
SELECT DISTINCT g.name
FROM goal g
INNER JOIN matches m
ON g.match_id = m.match_id
INNER JOIN team_match tm
ON tm.match_id = m.match_id
AND tm.home_away = 'away'
WHERE m.match_id = '1'
But instead of:
Messi
Suarez
I am getting:
Ronaldo
Messi
Suarez
It seams like my second INNER JOIN is totally ignored, even if I change from "home" to "away" I will get the same result.
The INNER JOIN is working correctly. Seems your database schema is the problem.
Why shouldn't Ronaldo be in the result set? You don't use the team_id anywhere. There is no information that Ronaldo was in the team that played home in the specified match.
A suggestion for a better schema:
Table teams
team_id
1
2
Table players:
playerid team_id name
1 1 Ronaldo
2 2 Messi
3 2 Suarez
Table matches
matchid hometeamid awayteamid
1 1 2
Table goals
matchid playerid
1 1
1 2
1 3
Then your query could look like this
SELECT p.Name FROM players p
INNER JOIN goals g ON (g.playerid = p.playerid)
INNER JOIN matches m ON (m.matchid = g.matchid AND m.awayteamid = p.team_id)
WHERE m.matchid = 1
You haven't proven that the first inner join is working either.
Try removing the blank lines

fetch parent category name if searching word is found subcategory of category master

i want to fetch parentcategory name.
SELECT u.id,u.fullname,u.email,u.ServiceDescription,
u.Skills,c.Name,r.Reviews,r.RatingValue,ru.Id,
ru.Fullname FROM UserDetails u
INNER JOIN VendorInCategory v ON v.VendorId=u.Id
INNER JOIN CategoryMaster c ON v.CategoryId=c.Id
left join Review r
on r.VendorId = u.id
left JOIN UserDetails ru ON r.CustomerId = ru.id
WHERE ((u.ServiceDescription LIKE '%Plaster%') OR (u.Skills LIKE '%Plaster%') OR
(c.Name LIKE '%Plaster%'))
ORDER BY ISNULL(r.RatingValue, 0) DESC;
now as you can see from below link my database design:
calculate average rating in sql server
here you can see plaster is subcategory of Construction(Id:40)
so i want to fetch parentcategory if any word i am searching for is found in categorymaster.
if word is found in subcategory then fetch its parentcategory name else fetch parentcategory name only.
can anybody please edit my query to achieve this functionality???
UserDetails:
id Name Servicedescription Skills
1 john Plaster plaster
2 abc construction construction
3 xyz plaster plaster
4 pqr null null(not vendor)
5 lmn null null(not vendor)
Review
id CustomerId Vendorid rating reviews
1 4 1 3 fdd
2 5 1 3 dfg
Now if i am seraching for "Plaster"
then output should be:
VendorId ServiceDescription Skills rating customername reviews ParentCategory
1 plaster plaster 3 pqr fdd construction
3 plaster plaster 3 lmn dfg Construction
here Construction(Id 40) is the ParentCategory of Plaster(Id 44) as u can see in image.if plaster does not have parentid then ParentCategory name should be plaster only.
Try this..
SELECT u.id,u.fullname,u.email,u.ServiceDescription,
u.Skills,c.Name,r.Reviews,r.RatingValue,ru.Id,
ru.Fullname,ISNULL(c1.Name,c.Name) AS CategoryName FROM UserDetails u
INNER JOIN VendorInCategory v ON v.VendorId=u.Id
INNER JOIN CategoryMaster c ON v.CategoryId=c.Id
LEFT JOIN CategoryMaster c1 ON c1.Id=c.ParentID
left join Review r
on r.VendorId = u.id
left JOIN UserDetails ru ON r.CustomerId = ru.id
WHERE ((u.ServiceDescription LIKE '%Plaster%') OR (u.Skills LIKE '%Plaster%') OR
(c.Name LIKE '%Plaster%'))
ORDER BY ISNULL(r.RatingValue, 0) DESC;
The below query will give parent:
SELECT c.Name AS Name,c1.Name As Parent FROM CategoryMaster c
LEFT JOIN CategoryMaster c1 on c1.ParentID=c.ID
Use Common table expression (CTE)
Recursive CTE calls
Sample User table structure
userId userName managerId
----------- ---------------- -----------
1 John NULL
2 Charles 1
3 Nicolas 2
4 Neil 5
5 Lynn 1
6 Vince 5
7 Claire 6
In order to get all top level managers name we need to use CTE recursive call.
WITH UserCTE AS (
SELECT userId, userName, managerId,0 AS steps
FROM dbo.Users
WHERE userId = 7
UNION ALL
SELECT mgr.userId, mgr.userName, mgr.managerId, usr.steps +1 AS steps
FROM UserCTE AS usr
INNER JOIN dbo.Users AS mgr
ON usr.managerId = mgr.userId
)
SELECT * FROM UserCTE AS u;
The above query will return all the managers name of userid = 7. Below is the output
userId userName managerId steps
----------- ---------------- ----------- -----------
7 Claire 6 0
6 Vince 5 1
5 Lynn 1 2
1 John NULL 3