'SQL placement join with student, friend, package
Issue:
You are given three tables: Students, Friends and Packages.
Students contains two columns: ID and Name.
- Friends contains two columns: ID and Friend_ID (ID of the ONLY best friend).
- Packages contains two columns: ID and Salary (offered salary in $ thousands per month).
Write a query to output the names of those students whose best friends got offered a higher salary than them. Names must be ordered by the salary amount offered to the best friends. It is guaranteed that no two students got same salary offer.
Code:
This is the code that I have come up with but it does not produce correct results. Can anyone let me know why?
select TableA.name
from
(select s.id,s.name,p.salary from students s inner join packages p on s.id=p.id) TableA,
(select f.id,f.friend_id, p2.salary from friends f inner join packages p2 on f.friend_id=p2.id) TableB
where TableA.id=TableB.id And TableA.salary>TableB.salary
order by TableB.salary desc;
Solution 1:[1]
I think in your query you wrote AND TableA.salary < TableB.salary
instead of AND TableA.salary > TableB.salary
.
Moreover I think your query can be written in a more synthetic way.
On MSSQL (but it works on MYSQL too, as query is very basic), you can try to use this one:
SELECT s.id
,s.NAME
,p.salary
, f.friend_id, p2.salary as friend_salary
FROM students s
INNER JOIN packages p ON s.id = p.id
LEFT JOIN friends f ON f.id = s.id
LEFT JOIN packages p2 ON f.friend_id = p2.id
WHERE p.salary <= p2.salary
ORDER BY s.id;
Output:
id NAME salary friend_id friend_salary
1 John 1000 2 1200
3 Pete 800 1 1000
Sample data:
CREATE TABLE students (id int, NAME VARCHAR(30));
CREATE TABLE packages (id int, salary INT);
CREATE TABLE friends (id int, friend_id INT);
INSERT INTO students values (1,'John');
INSERT INTO students values (2,'Arthur');
INSERT INTO students values (3,'Pete');
INSERT INTO packages values (1,1000);
INSERT INTO packages values (2,1200);
INSERT INTO packages values (3,800);
INSERT INTO friends values (1,2);
INSERT INTO friends values (2,3);
INSERT INTO friends values (3,1);
Solution 2:[2]
you have written 'where TableA.salary>TableB.salary' implying that you want to find rows where your salary is > than your friends. But the question asked was the opposite (to find names where the firends salary is > than your salary) so you can change that to 'where TableB.salary>TableA.salary' and it should work.
select my_name from
(select s.id as my_id,s.name my_name,p.salary as my_salary from students s
inner join packages p on s.id=p.id) as my_tbl inner join (select f.id as
id,f.friend_id as frnd_id,p.salary as frnd_salary from friends f inner join
packages p on f.friend_id=p.id ) as frnd_tbl on my_id=id where
frnd_salary>my_salary order by frnd_salary;
Solution 3:[3]
I used CTE for easy code readability. I am not sure whether it is fully optimized or not. But, it yields the result as expected from the question.
with std_salary as (
SELECT s.id, s.name, p.salary
FROM Students s
JOIN Packages p
ON s.id=p.id),
friend_salary as (
SELECT f.id, p.salary
FROM Friends f
JOIN Packages p
ON f.friend_id=p.id
)
SELECT name
FROM
(SELECT std_salary.name, std_salary.salary as own, friend_salary.salary as friend
FROM std_salary
JOIN friend_salary
ON std_salary.id=friend_salary.id) as final
WHERE final.own<final.friend
ORDER BY final.friend;
Solution 4:[4]
This worked for me in MySql -
select name from Students
inner join Friends on Friends.ID = Students.ID
inner join Packages P1 on P1.ID = Students.ID
inner join Packages P2 on P2.ID = Friends.Friend_ID
where P2.salary > P1.salary
order by P2.salary;
Solution 5:[5]
Well using self join we can solve this and similar problems easily
SELECT s.name from students AS s
JOIN friends AS f
ON s.id=f.id
JOIN packages AS p1
on s.id=p1.id
JOIN packages AS p2
ON p2.id=f.friend_id
WHERE p1.salary<=p2.salary
ORDER BY p2.salary
For better understanding go through SELF JOIN TOPIC IN SQL
Solution 6:[6]
This worked for me in Oracle:
select s.name
from students s, friends f, packages p1, packages p2
where s.id = f.id
and s.id = p1.id
and p2.id = f.friend_id
and p1.salary < p2.salary
order by p2.salary;
Solution 7:[7]
This worked for me in MS SQL
SELECT a.name
FROM (SELECT students.id as main_id, students.name, packages.salary
FROM students join packages on students.id = packages.id) a
JOIN (SELECT f.id as main_id1, p.salary
FROM friends f JOIN packages p ON f.friend_id = p.id) b
ON a.main_id = b.main_id1
WHERE b.salary>a.salary
ORDER BY b.salary ASC;
Solution 8:[8]
WITH CTE AS
(SELECT s.name, p.salary, f.friend_id
FROM Students s
JOIN Friends f
ON s.id = f.id
JOIN Packages p
ON s.id = p.id)
SELECT c.name FROM CTE c
JOIN students s1
ON s1.id = c.friend_id
JOIN packages p1
ON c.friend_id = p1.id
WHERE c.salary < p1.salary
ORDER BY p1.salary;
Solution 9:[9]
select s_name from
(select s.id as s_id, s.name as s_name, p.salary as s_salary
from
Students s
Join
Packages p
on s.id = p.id) a
Join
(select f.id as s_id,friend_id as f_id, s.name as f_name, p.salary as f_salary
from
friends f
Join
Packages p
Join
Students s
on friend_id = p.id
and
s.id = friend_id)b
ON
a.s_id = b.s_id
where s_salary < f_salary
order by f_salary
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | user9699836 |
Solution 4 | jatin_5 |
Solution 5 | Ramkinkar |
Solution 6 | buddemat |
Solution 7 | arajani |
Solution 8 | Vikas Singh Parmar |
Solution 9 | Monirrad |