SQL Server query to find parent names of child - sql-server

i have a table like this
ID Name Mother Father
1 Sue NULL NULL
2 Ed NULL NULL
3 Emma 1 2
4 Jack 1 2
5 Jane NULL NULL
6 Bonnie 5 4
7 Bill 5 4
and i need output as below
ID Name Mother Father
3 Emma sue ed
4 jack sue ed
6 bonnie jane jack
7 bill jane jack
i have tried writing query with join n cte but couldnt come up with the logic , can someone please help me out

SELECT t.ID, t.Name, m.Name, f.Name
FROM your_table t
INNER JOIN your_table m ON m.ID = t.Mother
INNER JOIN your_table f ON f.ID = t.Father
Use LEFT JOIN if you want to include records without Mother and/or Father nodes:
SELECT t.ID, t.Name, ISNULL(m.Name, 'Orphan') Mother, ISNULL(f.Name, 'Orphan') Father
FROM your_table t
LEFT JOIN your_table m ON m.ID = t.Mother
LEFT JOIN your_table f ON f.ID = t.Father

try something like this:
select
p.id, p.name, p1.name as mother, p2.name as father
from people p
inner join people p1 on p1.id = p.mother
inner join people p2 on p2.id = p.father

Select Query
SELECT A.*
FROM tbl A
,tbl M
,tbl F
WHERE A.Mother = M.ID
AND A.Father = F.ID
without inner join..

Related

Query performances by evaluating Execution Plan (Join First Row)

I have the following tables:
Customers
ID Name
============
1 John
2 Alice
3 Bob
Orders
ID CustomerID Status
==========================
1001 1 1
1002 2 1
1003 2 2
1004 3 2
I'd like to join tables showing one entry per customer only (the one with lowest Status) i.e.
ID Name OrderID
======================
1 John 1001
2 Alice 1002
3 Bob 1004
Thanks to the answer to this question, I chose 2 solutions which produce the same output:
Solution 1
SELECT c.id, c.name, o.id FROM customers AS c
INNER JOIN orders AS o ON
c.id = o.customerid
WHERE o.status = (SELECT MIN(status) FROM orders WHERE customerid = c.id)
Solution 2
SELECT c.id, c.name, o.id FROM customers as c
INNER JOIN orders AS o ON
o.id = (SELECT TOP 1 id FROM orders WHERE customerid = c.id ORDER BY status)
Trying to understand which one runs faster, I used SQL Fiddle View Execution Plan which gave the following:
Solution 1
Solution 2
How to interpret those diagrams and which one performs faster?
Using MS SQL Server 2016.
Here's my breakdown and the last one is my suggestion to you.
Query Cost 67%
SELECT c.id, c.name, o.id FROM #Customers AS c
INNER JOIN #Orders AS o ON
c.id = o.customerid
WHERE o.status = (SELECT MIN(status) FROM #Orders WHERE customerid = c.id)
Query Cost 66%
SELECT c.id, c.name, o.id FROM #Customers as c
INNER JOIN #Orders AS o ON
o.id = (SELECT TOP 1 id FROM #Orders WHERE customerid = c.id ORDER BY status)
Query Cost 47%
SELECT
x.CustID,
x.Name,
x.OrderID
FROM (SELECT
C.id CustID,
c.Name,
o.ID OrderID,
o.status,
ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY o.status) rn
FROM #Customers c
INNER JOIN #Orders o
ON o.CustomerID = c.ID) x
WHERE x.rn = 1

Concat Multiple Select responses

I am very new the DB scripting, but I have the following Select statements returning 3 different Data sets from 2 separate tables.
SELECT
A.CustomerId,
C.Customername
FROM
BankCustomer C
RIGHT JOIN
BankAssociation A
ON C.CustomerId = A.CustomerId
SELECT
A.TypeId,
T.Type
FROM
BankAssociation A
LEFT JOIN
BankTypes T
On A.TypeId = T.TypeId
SELECT
A.CustomerId2,
C.Customername
FROM
BankCustomer C
RIGHT JOIN
BankAssociation A
On C.CustomerId = A.CustomerId2
The multiple SELECTstatements will return DATA in separate tables as such:
SELECT 1
Damian Wayne
Peter Parker
SELECT 2
CLEANS
BUILDS
SELECT 3
Bruce Wayne
Ben Parker
My question:
I want to concatenate the Rows with a verb that will display the Rows something like this
Damian Wayne CLEANS for Bruce Wayne
Peter Parker BUILDS for Ben Parker
You can try this.
SELECT CONCAT(C.CustomerName , ' ' , T.Type , ' for ' , C2.CustomerName ) FROM
BankAssociation A
LEFT JOIN BankCustomer C ON C.CustomerId = A.CustomerId
LEFT JOIN BankCustomer C2 ON C2.CustomerId = A.CustomerId2
LEFT JOIN BankTypes T On A.TypeId = T.TypeId

query to return null values when none exist in one table

I need to list out 6 medical offices in one column, and the patient's full name in the other. If the patient has never visited that office before, then a NULL should appear.
The table structures are simple with MedicalOffice having an ID,
Name, and a few miscellaneous columns.
MedicalProcedure has the
officeID, patientID, patient's full name, and some miscellaneous
columns.
There is only one ID per office in the MedicalOffice table, but MedicalProcedure can have many officeIDs per patient and even the same officeID for the same patient more than once.
Following some answers I found here on SO, I tried a left outer join:
select m.Name, p.FullName
from MedicalOffice m
left outer join MedicalProcedure p ON m.ID = p.officeID
where m.ID IN (1,2,3,4,5,6)
AND p.patientID = 111
GROUP BY m.Name, p.patientID
ORDER BY m.Name
Then a left join:
select m.Name, p.FullName
from MedicalOffice m
left join MedicalProcedure p ON m.ID = p.officeID
where m.ID IN (1,2,3,4,5,6)
AND p.patientID = 111
GROUP BY m.Name, p.patientID
ORDER BY m.Name
but I only get the offices where a record exists in the MedicalProcedure table like this:
Name | FullName
----------------------------------
Office 1 Smith, John
Office 2 Smith, John
Office 4 Smith, John
But, if patientID 111 had 3 records in the MedicalProcedure table for Offices 1,2, and 4, the results should look like this:
Name | FullName
----------------------------------
Office 1 Smith, John
Office 2 Smith, John
Office 3 NULL
Office 4 Smith, John
Office 5 NULL
Office 6 NULL
Is there a way to get the results I need?
Thanks!
Just move p.patientID = 111 condition into ON clause. In Where it effectively changes outer join into inner join:
Select
Distinct --< Substitute for Group By
m.Name, p.FullName
From MedicalOffice m
Left Join MedicalProcedure p On m.ID = p.officeID AND p.patientID = 111
Where m.ID IN (1,2,3,4,5,6)
/* Group By m.Name, p.patientID */ --< won't work in this example
Order By m.Name
Remove
m.ID IN (1,2,3,4,5,6)
This condition will stop null value showup

SQL Server : update from one table with Select and Join two another table

I have two tables:
Teams
Id Name
1 Manchester
2 Arsenal
3 Inter
4 Milan
Games
GameId FirstTeamId GoalsFirstTeam GoalsSecondTeam SecondTeamId
1 1 0 0 2
2 3 2 3 4
3 1 1 1 3
I want to update into GameResult with a select and join from two tables Games and Teams like this:
GameId FirstTeam GoalsFT GoalsST SecondTeam
1 Manchester 0 0 Arsenal
2 Inter 2 3 Milan
3 Manchester 1 1 Inter
I tried this:
UPDATE GameResult
SET GameId = (SELECT GameId
FROM Games),
FirstTeam = (SELECT t1.Name AS FirstTeam
FROM Games AS g
INNER JOIN Teams t1
ON g.FirstTeamId = t1.Id),
GoalsFT = (SELECT GoalsFirstTeam
FROM Games),
GoalsST = (SELECT GoalsSecondTeam
FROM Games),
SecondTeam = (SELECT t2.Name AS SecondTeam
FROM Games AS g
INNER JOIN Teams t2
ON g.SecondTeamId = t2.Id)
...but it didn't work.
Can somebody help me with this ?
try this
UPDATE GameResult
SET GameId = G.GameId,
FirstTeam = T1.Name,
GoalsFT = G.GoalsFirstTeam,
GoalsST = G.GoalsSecondTeam,
SecondTeam = T2.Name
FROM Games G INNER JOIN Teams T1 ON G.FirstTeamID=T1.ID
INNER JOIN Teams T2 ON G.SecondTeamId=T2.ID
UPDATE:
if you want just to insert new records into GameResult from the 2 other tables, try this
INSERT GameResult (GameId, FirstTeam, GoalsFT, GoalsST, SecondTeam)
SELECT G.GameId, T1.Name, G.GoalsFirstTeam, G.GoalsSecondTeam, T2.Name
FROM Games G INNER JOIN Teams T1 ON G.FirstTeamID=T1.ID
INNER JOIN Teams T2 ON G.SecondTeamId=T2.ID
It seems that your table 'GameResult' hasn't got any records to update. Either fill it first and then use the abovementioned solution by Pupa Rebbe, or use a Merge statement to insert, update and (if needed) delete records.
For more information, see this MS library
Simple solution:
Delete From GameResult
Go
Insert GameResult (GameId,
FirstTeam,GoalsFT, GoalsST, SecondTeam)
SELECT g.GameId,
t1.Name AS FirstTeam,
g.GoalsFirstTeam, g.GoalsSecondTeam,
t2.Name AS SecondTeam
FROM Game g
INNER JOIN Team t1 ON g.FirstTeamId = t1.Id
INNER JOIN Team t2 ON g.SecondTeamId = t2.Id

Inner Join on Empty Values

TableName:Emp
EmpId EmpName EmpAddressId
1 Ram 100
2 Ravi
3 Raj 102
4 Kiran
5 Bujji 101
TableName:Address
AddressId Address
101 India
102 Uk
103 US
select E.*,A.Address from EMP E inner join Address A
on E.EmpId=2 and E.EmpAddressId='' or E.EmpAddressId=A.AddressId
out put should display as for EmpId:2
------------------------------
EmpId EmpName EmpAddressId Address
2 Ravi
for EmpId:3
------------
EmpId EmpName EmpAddressId Address
3 Raj 102 Uk
For employee 2 there is no EmpAddressId but here requirement is need to display as null values or empty values.
can any one help this.
Just replace INNER JOIN with a LEFT JOIN (or LEFT OUTER JOIN). That will result in NULL for all columns from Address table if there's no match. Also, you can replace your join condition with a simpler version:
select E.EmpId, E.EmpName, E.EmpAddressId, A.Address
from EMP E left join Address A
on E.EmpAddressId=A.AddressId
where E.EmpId=2
More on outer joins on MSDN.
Inner join will yield to null if any of the joining table is null.. If all the table has value then use inner join else go for left join. It ensures that atleast you will get let joined table values.
For this ,you use left join
select e.EmpId, e.EmpName, e.EmpAddressId, a.Address
from EMP e left join Address a
on e.EmpAddressId=a.AddressId
where e.EmpId=2

Resources