How to join two tables with three pairs - sql

I have two tables that I want to combine (join) in SQL.
Table 1 Persons:
Person _Id
First_name
Last_name
135790
John
Smith
246801
Lucas
Williams
054953
George
Johnson
460235
Adam
White
Table 2 Loans:
Borrower_Id
resident1_id
resident2_id
135790
246801
054953
460235
054953
135790
054953
246801
135790
The expected result:
Borrower_FN
Borrower_LN
resident1_FN
resident1_LN
resident2_FN
resident1_LN
John
Smith
Lucas
Williams
George
Johnson
Adam
White
George
Johnson
John
Smith
George
Johnson
Lucas
Williams
John
Smith
How can I join it?

This is a way you can achieve the result:
select p.First_name as Borrower_FN, p.Last_name as Borrower_LN,
p2.First_name as resident1_FN, p2.Last_name as resident1_LN,
p3.First_name as resident2_FN, p3.Last_name as resident2_LN
from Loans l
inner join Persons p on p.Person_id = l.Borrower_id
inner join Persons p2 on p2.Person_id = l.resident1_id
inner join Persons p3 on p3.Person_id = l.resident2_id

Related

SQL join manager from same table onto a row with their employees

To start, here's a dummy table I've made to show the data I'm working with:
employee
title
division
email
Boss Person
boss
o
bp#email
John Smith
supervisor
a
jos#email
Jane Smith
supervisor
b
jas#email
Leo Messi
employee
a
lm#email
Amanda Kessel
employee
a
ak#email
Derek Jeter
employee
b
dj#email
I want to end up with the following info:
employee
title
division
email
supervisor_name
supervisor_email
Boss Person
boss
o
bp#email
NULL
NULL
John Smith
supervisor
a
jos#email
Boss Person
bp#email
Jane Smith
supervisor
b
jas#email
Boss Person
bp#email
Leo Messi
employee
a
lm#email
John Smith
jos#email
Amanda Kessel
employee
a
ak#email
John Smith
jos#email
Derek Jeter
employee
b
dj#email
Jane Smith
jas#email
I've looked through and tried documentation at:
https://www.sqltutorial.org/sql-self-join/
SQL Server : LEFT JOIN EMPLOYEE MANAGER relationship
One of the big differences here is I don't have any employee or manager id column to work with.
If you're a supervisor for a division, ie John Smith is a supervisor in division a, then you manage all the employees in division a. Meanwhile, all the supervisors answer to the boss in division o, while the boss answers to no one.
Here is the best code I've tried so far:
select e.*, b.employee as supervisor, b.email as supervisor_email
from employees e, employees b
where b.division = e.division
and
b.title like '%supervisor%'
This got me close, it returned:
employee
title
division
email
supervisor_name
supervisor_email
John Smith
supervisor
a
jos#email
John Smith
jos#email
Jane Smith
supervisor
b
jas#email
Jane Smith
jas#email
Leo Messi
employee
a
lm#email
John Smith
jos#email
Amanda Kessel
employee
a
ak#email
John Smith
jos#email
Derek Jeter
employee
b
dj#email
Jane Smith
jas#email
So, it got the employee info right, but left out the Boss record and placed the supervisors as their own supervisor. I think I need some kind of case or if statement here, but I'm not sure.
Please let me know if this makes sense or if any further clarification is needed.
You could try using a LEFT JOIN and work with two conditions:
when division is the same and we're dealing with the relationship employee < supervisor
when the relationship is supervisor < boss
Here's how I did it:
SELECT t1.*,
t2.employee,
t2.email
FROM tab t1
LEFT JOIN tab t2
ON (t1.division = t2.division AND
t2.title = 'supervisor' AND
t1.title = 'employee')
OR (t2.title = 'boss' AND
t1.title = 'supervisor')
You'll find an SQL fiddle here.
If you want to update the current table (if columns are available), you can do the following (more or less the same as #lemon) :
UPDATE testing t1 JOIN testing t2 ON t2.`division`=t1.division OR t2.division="o" SET
t1.supervisor_name=t2.`employee`, t1.supervisor_email=t2.email
WHERE (CASE
WHEN t1.`title`="employee" THEN t2.title="supervisor"
WHEN t1.`title`="supervisor" THEN t2.title="boss"
END);
SELECT * FROM testing;

oracle exercise question in my data using 2 table information

person
name home st
JAMES LA L1
MIKE BOSTON B1
ANTON LA L1
LEE NY N1
BROWN NY N2
mentor
name m_name
JAMES ANTON
MIKE (null)
ANTON (null)
LEE BROWN
BROWN (null)
I want to get information from people who live in the same st and cities as mentors.
In the example I gave, it is JAMES who meets that condition.
How could I get that information?..
my version oracle11g
This sounds like two joins:
select pn.name
from mentor m join
person pn
on pn.name = m.name join
person pm
on pm.name = m.m_name
where pn.street = pm.street and pn.city = pm.city;

How to solve this using a subquery in a from clause?

Display author, title, retail and retail price of all books whose retail price is the highest for the specific author.
I have the query below. I'm kinda confused how to do a subquery in a from clause.
select lname, fname, title, retail
from author natural join bookauthor
natural join books
where retail=(select max(retail)
from books);
Below is the data from the database that I'm using
FNAME LNAME TITLE RETAIL
---------- ---------- ------------------------------ ----------
SAM SMITH BODYBUILD IN 10 MINUTES A DAY 30.95
LISA PORTER BODYBUILD IN 10 MINUTES A DAY 30.95
JANICE JONES REVENGE OF MICKEY 22
TAMARA KZOCHSKY BUILDING A CAR WITH TOOTHPICKS 59.95
TINA PETERSON DATABASE IMPLEMENTATION 55.95
JUAN ADAMS DATABASE IMPLEMENTATION 55.95
JAMES AUSTIN DATABASE IMPLEMENTATION 55.95
JACK BAKER COOKING WITH MUSHROOMS 19.95
JAMES AUSTIN HOLY GRAIL OF ORACLE 75.95
LISA WHITE HANDCRANKED COMPUTERS 25
WILLIAM WHITE HANDCRANKED COMPUTERS 25
JANICE JONES E-BUSINESS THE EASY WAY 54.5
ROBERT ROBINSON PAINLESS CHILD-REARING 89.95
OSCAR FIELDS PAINLESS CHILD-REARING 89.95
JACK BAKER PAINLESS CHILD-REARING 89.95
SAM SMITH THE WOK WAY TO COOK 28.75
ROBERT ROBINSON BIG BEAR AND LITTLE DOVE 8.95
SAM SMITH HOW TO GET FASTER PIZZA 29.95
WILLIAM WHITE HOW TO MANAGE THE MANAGER 31.95
LISA WHITE SHORTEST POEMS 39.95
20 rows selected.
You could use this:
SELECT lname, fname, title, retail
FROM author a
INNER JOIN bookauthor ba
ON a.id = ba.author_id
INNER JOIN books b
ON b.id = ba.book_id
WHERE (ba.author_id, ba.retail) IN (
SELECT ba1.author_id, MAX(b1.retail)
FROM books b1
INNER JOIN bookauthor ba1
ON ON b1.id = ba1.book_id
GROUP BY ba1.author_id
);
Do not use NATURE JOIN. This is bad way of join, for all learner and programmer.
(And change author_id, book_id to column name of your specific table)
Other way:
SELECT lname, fname, title, retail
FROM author a
INNER JOIN bookauthor ba
ON a.id = ba.author_id
INNER JOIN books b
ON b.id = ba.book_id
INNER JOIN(
SELECT ba1.author_id, MAX(b1.retail) retail
FROM books b1
INNER JOIN bookauthor ba1
ON ON b1.id = ba1.book_id
GROUP BY ba1.author_id
) mr
ON
ba.author_id = mr.author_id
AND ba.retail = mr.retail
;
This can be solved using ether an inner join:
select lname, fname, title, retail
from author natural join bookauthor
natural join books
inner join (select max(retail) as max_retail, authorid
from books
group by authorid) b
on books.authorid = b.authorid and books.retail = b.max_retail
or a correlated subquery:
select lname, fname, title, retail
from author natural join bookauthor
natural join books
where retail=(select max(retail)
from books b where b.authorid=author.authorid);
Please note, because you are using the natural join it is impossible for us to know the actual column names you used for the joins. Therefore I have assumed that the authorid foreign key is called authorid

How do I transpose multiple rows to columns in SQL

My first time reading a question on here.
I am working at a university and I have a table of student IDs and their supervisors, some of the students have one supervisor and some have two or three depending on their subject.
The table looks like this
ID Supervisor
1 John Doe
2 Peter Jones
2 Sarah Jones
3 Peter Jones
3 Sarah Jones
4 Stephen Davies
4 Peter Jones
4 Sarah Jones
5 John Doe
I want to create a view that turns that into this:
ID Supervisor 1 Supervisor 2 Supervisor 3
1 John Doe
2 Peter Jones Sarah Jones
3 Peter Jones Sarah Jones
4 Stephen Davies Peter Jones Sarah Jones
5 John Doe
I have looked at PIVOT functions, but don't think it matches my needs.
Any help is greatly appreciated.
PIVOT was the right clue, it only needs a little 'extra' :)
DECLARE #tt TABLE (ID INT,Supervisor VARCHAR(128));
INSERT INTO #tt(ID,Supervisor)
VALUES
(1,'John Doe'),
(2,'Peter Jones'),
(2,'Sarah Jones'),
(3,'Peter Jones'),
(3,'Sarah Jones'),
(4,'Stephen Davies'),
(4,'Peter Jones'),
(4,'Sarah Jones'),
(5,'John Doe');
SELECT
*
FROM
(
SELECT
ID,
'Supervisor ' + CAST(ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Supervisor) AS VARCHAR(128)) AS supervisor_id,
Supervisor
FROM
#tt
) AS tt
PIVOT(
MAX(Supervisor) FOR
supervisor_id IN ([Supervisor 1],[Supervisor 2],[Supervisor 3])
) AS piv;
Result:
ID Supervisor 1 Supervisor 2 Supervisor 3
1 John Doe NULL NULL
2 Peter Jones Sarah Jones NULL
3 Peter Jones Sarah Jones NULL
4 Peter Jones Sarah Jones Stephen Davies
5 John Doe NULL NULL
You will notice that the assignment to Supervisor X is done by ordering by the Supervisor-VARCHAR. If you want the ordering done differently, you might want to include an [Ordering] column; then change to ROW_NUMBER() OVER(PARTITION BY ID ORDER BY [Ordering]). Eg an [Ordering] column could be an INT IDENTITY(1,1). I'll leave that as an excercise to you if that's what's really needed.

SQL - Return number times a value results from a query

I'm fairly new to SQL server (this is my second post on StackOverflow). I'm currently using SQL Server 2008 R2. I have a few tables that I've joined with the following query:
SELECT pt.first_name, pt.last_name, pt.provider_id,
pt.last_visit_date, pl.last_name
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
ORDER BY provider_id
The result of the above query looks something like this:
first_name last_name provider_id last_visit_date last_name
Smith John 1 04/25/2012 Johnson
Doe Jane 1 02/25/2012 Johnson
Davies Ann 1 03/15/2012 Johnson
Dupree David 1 11/20/2012 Johnson
Jones Becky 1 04/21/2012 Smith
Diaz Mike 1 02/12/2012 Smith
Williams Allison 1 08/05/2012 Smith
Taylor Joe 1 10/01/2012 Smith
I would rather simply get the following result:
last_name NoOfPatients
Johnson 4
Smith 4
Could someone please help me?
Try :
SELECT pl.last_name, count(*) NoOfPatients
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
GROUP BY pl.last_name
You need to read about how to use group in querys, basically what you need to do is count the number of patients and group by providers.
SELECT pt.last_name, COUNT(pt.*) NoOfPatients
FROM dbo.pm_patient pt
INNER JOIN dbo.ProviderList pl
ON pt.provider_id = pl.provider_id
WHERE pt.last_visit_date >= '02/01/2012' AND pt.last_visit_date <= '02/01/2013'
ORDER BY provider_id
GROUP BY pt.last_name