JOINING Same Table gives duplicate information - sql

I want to join the same table to get some information.
I have a Person Table
PersonId, FirstName, LastName, Address
Also Patient Table
PatientId, PersonId, ResponsiblePersonId
Below is the query i tried to get Patient's FirstName, Last Name also the Responsible Person FirstName, Last Name. For this I JOINED Person table once again to get Responsible Persons First, Last names.
But I got many duplicate records.
SELECT PAT.PatientId
,PER.PersonNumber
,PER.FirstName
,PER.LastName
,RES_PER.FirstName AS ResFirstName
,RES_PER.LastName AS ResLastName
,PER.Address
FROM dbo.Patient AS PAT
INNER JOIN dbo.Person AS PER
ON PAT.PersonId = PER.PersonId
INNER JOIN dbo.Person AS RES_PER
ON PAT.ResponsiblePersonId = PER.PersonId
How can i get Patient FirstName, LastName & Responsible Person's First Name, Last Name for the patient record?

Basically, you need to join table Person twice on table Patient in order to get the two dependent columns on it.
SELECT b.FirstName Patient_FirstName,
b.LastName Patient_LastName,
b.Address Patient_Address,
c.FirstName Responsible_Firstname,
c.LastName Responsible_LastName,
c.Address Responsible_Address
FROM Patient a
INNER JOIN Person b
ON a.PersonID = b.PersonID
INNER JOIN Person c
ON a.ResponsiblePersonId = c.PersonID
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins

All you need to do is replace PER with RES_PER in the very last bit of your SQL. (i.e. PER.PersonId becomes RES_PER.PersonId).
SELECT PAT.PatientId
,PER.PersonNumber
,PER.FirstName
,PER.LastName
,RES_PER.FirstName AS ResFirstName
,RES_PER.LastName AS ResLastName
,PER.Address
FROM dbo.Patient AS PAT
INNER JOIN dbo.Person AS PER
ON PAT.PersonId = PER.PersonId
INNER JOIN dbo.Person AS RES_PER
ON PAT.ResponsiblePersonId = RES_PER.PersonId

Related

SQL query find records that not persists in other tables

I need to print all persons which are not students and not teachers. I have three tables. Oracle database. Code so far:
SELECT PersonID, FirstName, LastName, Gender, DateOfBirth
FROM PERSON
INNER JOIN STUDENT S ON PERSON.PersonID = S.StudentID
INNER JOIN TEACHER T ON PERSON.PersonID = T.TeacherID
WHERE PERSON.PersonID != S.StudentID
AND PERSON.PersonID != T.TeacherID;
I guess my query is wrong because it returns 0 results. Do you have any idea what must I change?
" my query is wrong because it returns 0 results"
Inner joins return records when there is a match. You're trying to find PERSON records which join to neither STUDENT nor TEACHER. So, change your query to use outer joins:
SELECT PersonID, FirstName, LastName, Gender, DateOfBirth
FROM PERSON
LEFT OUTER JOIN STUDENT S ON PERSON.PersonID = S.StudentID
LEFT OUTER JOIN TEACHER T ON PERSON.PersonID = T.TeacherID
WHERE S.StudentID is null
AND T.TeacherID is null;
This is an anti-join: it returns records from PERSON which don't match records in STUDENT and TEACHER.
Use not exists:
select p.*
from person p
where not exists (select 1 from teacher t where t.teacherid = p.personid) and
not exists (select 1 from students s where s.studentid = p.personid);
Although you can write this query with left join, I think the version using not exists is almost a direct translation of the question, making it easier to understand.
In Oracle, you can also write this using minus -- if you want only the id:
select personid
from person
minus
select teacherid
from teacher
minus
select studentid
from student;
--Try this with Left Outer Join...
SELECT
P.PersonID,
P.FirstName,
P.LastName,
P.Gender,
P.DateOfBirth
FROM PERSON P
LEFT OUTER JOIN STUDENT S ON P.PersonID = S.StudentID
LEFT OUTER JOIN TEACHER T ON P.PersonID = T.TeacherID
WHERE S.PersonID is null and T.PersonID is null

SQL explicit join filter condition

Using this relational schema, patient ID and staff ID are foreign keys with id.staff and pid.patient being unique keys:
staff(ID, fname, lname, role)
patient(pID, pFname, pLname, bdate, address, phone)
appointment(aptID, patientID, staffID, aptDate, aptTime)
procedures(procNum, pName, price)
aptDetail(aptID, procNo)
So say if I wanted to list the names of patients with appointments with a specific staff member, i.e John Smith, how would I do that explicitly?
I've managed implicitly, but I know this is kind of frowned upon, but I can't reach it without using WHERE statements.
Any help would be appreciated, any time I try and use INNER JOIN I seem to hit a wall if it's not a simple join.
Is this the type of query you're looking for?
select distinct pFname, pLname
from patient p
join appointment a on p.pID = a.patientID
join staff s on a.staffID = s.ID
where s.fname = 'John' and s.lname = 'Smith'
You can use inner join
select
a.pID
, a.pFname
, a.pLname
, a.bdate
, a.address
, a.phone
, b.aptDate
, b.aptTime
, c.fname
, c.lname
, c.role
from patient a
INNER JOIN appointment b on b.patientID = a.pID
INNER JOIN staff c on b.staffID = c.ID on concat(fname, ' ', lname ) ='John Smith'
Something like the following should work fine:
SELECT p.*
FROM appointment AS a
INNER JOIN staff AS s ON a.staffID = s.pID
INNER JOIN patient AS p ON a.patientID = p.pID
WHERE s.ID = <yourstaffid>;
select staff.fname, staff.role,
patient.pfname, plname, appoitment.aotdate
from staff, patient, appointment
where patient.pid=appointment.patientId
and staff.id=appointment.staffid

How do I query a table by list of values?

I have 3 tables:
Person
-----------
id
name
doctor_id
Doctor
-----------
id
name
Person_Doctor
-------------
id
person_id
doctor_id
The idea is that a person can have more than one doctor, and a doctor can have more than one patient (person).
What I want to do is get all of a person's doctors by id. Here's my prelim strategy:
SELECT * FROM Person_Doctor WHERE person_id=:id
and then map each Person_Doctor to the corresponding doctor by doctor_id. The thing with this approach is that I'll have to query the DB for each Person_Doctor object, seems expensive. Is there a better way to do this?
Select p.name as patient, d.name as doctor
From person as p inner join person_doctor as pd on pd.person_id = id
inner join doctor as d on pd.doctor_id = d.id
where p.id = SomeID
This is a fairly basic JOIN, which is a fundamental element of relational databases. I'd recommend once you've finished this assignment, studying up and perhaps taking a college level course in databases. The problems you'll encounter while working in SQL will all be harder than this one.
SELECT d.name as 'doctor name'
FROM doctor d
INNER JOIN person_doctor pd on d.doctor_id = pd.doctor_id
INNER JOIN person ON p p.person_id = pd.person_id
WHERE p.person_id = #id
SELECT DISTINCT p.id
FROM person p
join person_doctor pd
on p.id = pd.person_id
join doctor d
on pd.doctor_id = d.id
WHERE p.doctor_id IS NOT NULL

How to select SQL results based on multiple tables

I need to select results from one table based on certain matching values in a couple of other tables. I have the following tables:
person: id, firstname, lastname
team: id, teamname
player: id, person_id(FK), team_id(FK)
coach: id, person_id(FK), team_id(FK)
I need to return all the coaches and players names for each team. I've only ever used inner joins, and it doesn't seem like I can use those here, so any idea how to do this?
This will give you the coach:
SELECT team.Teamname, person.Firstname, person.Lastname
FROM person
JOIN coach ON person.id = coach.person_id
JOIN team ON coach.team_id = team.id
And this will give you the players:
SELECT team.Teamname, person.Firstname, person.Lastname
FROM person
JOIN player ON person.id = player.person_id
JOIN team ON player.team_id = team.id
So, the non-elegant, simple answer is to just toss it all together with UNION.
Just use an OR in the join to Team
SELECT
P.firstname,
P.lastname,
T.teamname
FROM
person p id
LEFT JOIN player pl
ON p.id = pl.person_id
LEFT JOIN coach c
ON p.id = c.person_id
LEFT JOIN team t
ON pl.team_id = t.id
or.c.team_id = t.id
Or if you perfer if and your database has COALESCE
LEFT JOIN team t
ON COALESCE(pl.team_id,c.team_id) = t.id

Return column name where Join condition is null

I have 2 tables: Employee and Person with the structure
Employee: Id, PersonId, Designation, IsActive
Person:Id, Name, Contact
Employee's PersonId column references Person's Id and can be null
I need to return an employee's Name and my join criteria is
SELECT emp.Salary, emp.Designation, emp.IsActive, p.Name from Employee emp
JOIN Person P ON P.Id = emp.PersonId or (p.Id is NULL AND emp.Id IS NULL)
This is incorrect as my requirement is:
If emp.PersonId = null, return p.Name = NULL
else return p.Name = Person's Name from table
Any pointers on this?
you need an outer join
SELECT emp.Salary, emp.Designation, emp.IsActive, p.Name
from Employee emp
left JOIN Person P
ON P.Id = emp.PersonId
when you use an INNER JOIN (or JOIN) you only select the rows matching the join critiria, in your example you would never nave a NULL Person name because if the Employee is not assiciated with a Person, that record would not be selected.
If you use OUTER JOIN (LEFT/RIGHT JOIN), ALL record from the main table (1st with LEFT and 2nd with RIGHT) will be selected.
Hope this helps.