简体   繁体   中英

sql self-join and subquery questions - stanford sql course

I have been thinking hard on this question and I think the problem of my code is probably due to the last part. I think I need use subquery like not exists or not in to solve the problem but cannot figure out how to fix the issue. Thanks!

Questions:

For each student A who likes a student B where the two are not friends, find if they have a friend C in common (who can introduce them!). For all such trios, return the name and grade of A, B, and C.

My code:

select h1.name, h1.grade, h2.name, h2.grade, h3.name, h3.grade 
from highschooler h1, 
     highschooler h2, 
     highschooler h3, 
     likes, 
     friend f1, 
     friend f2
where h1.id = likes.id1 
and h2.id = likes.id2 
and h3.id = f1.id2 
and h2.id = f2.id1 
and h3.id = f2.id2 
and h1.id = f1.id1 
and h2.id <> f1.id2

Table: Highschooler

ID  name    grade
1510    Jordan  9
1689    Gabriel 9
1381    Tiffany 9
1709    Cassandra   9
1101    Haley   10
1782    Andrew  10
1468    Kris    10
1641    Brittany    10
1247    Alexis  11
1316    Austin  11
1911    Gabriel 11
1501    Jessica 11
1304    Jordan  12
1025    John    12
1934    Kyle    12
1661    Logan   12

Friend

ID1 ID2
1510    1381
1510    1689
1689    1709
1381    1247
1709    1247
1689    1782
1782    1468
1782    1316
1782    1304
1468    1101
1468    1641
1101    1641
1247    1911
1247    1501
1911    1501
1501    1934
1316    1934
1934    1304
1304    1661
1661    1025
1381    1510
1689    1510
1709    1689
1247    1381
1247    1709
1782    1689
1468    1782
1316    1782
1304    1782
1101    1468
1641    1468
1641    1101
1911    1247
1501    1247
1501    1911
1934    1501
1934    1316
1304    1934
1661    1304
1025    1661

Likes

ID1 ID2
1689    1709
1709    1689
1782    1709
1911    1247
1247    1468
1641    1468
1316    1304
1501    1934
1934    1501
1025    1101

it came out a bit more complicated then anticipated, but it seems to work

select * into #likes
from(
select '1689'ID1,'1709'ID2  union  
select '1709','1689'        union 
select '1782','1709'        union 
select '1911','1247'        union 
select '1247','1468'        union 
select '1641','1468'        union 
select '1316','1304'        union 
select '1501','1934'        union 
select '1934','1501'        union 
select '1025','1101')x

select * into #Highschooler
from (
select '1510'ID,'Jordan'name, 9 grade   union
select '1689','Gabriel', 9                          union
select '1381','Tiffany', 9                          union
select '1709','Cassandra', 9                        union
select '1101','Haley', 10                           union
select '1782','Andrew', 10                          union
select '1468','Kris', 10                            union
select '1641','Brittany', 10                        union
select '1247','Alexis', 11                          union
select '1316','Austin', 11                          union
select '1911','Gabriel', 11                         union
select '1501','Jessica', 11                         union
select '1304','Jordan', 12                          union
select '1025','John', 12                            union
select '1934','Kyle', 12                            union
select '1661','Logan', 12       ) x             


  select * into #Friend
  from(
select '1510'ID1,'1381'ID2    union
select '1510','1689'          union
select '1689','1709'          union
select '1381','1247'          union
select '1709','1247'          union
select '1689','1782'          union
select '1782','1468'          union
select '1782','1316'          union
select '1782','1304'          union
select '1468','1101'          union
select '1468','1641'          union
select '1101','1641'          union
select '1247','1911'          union
select '1247','1501'          union
select '1911','1501'          union
select '1501','1934'          union
select '1316','1934'          union
select '1934','1304'          union
select '1304','1661'          union
select '1661','1025'          union
select '1381','1510'          union
select '1689','1510'          union
select '1709','1689'          union
select '1247','1381'          union
select '1247','1709'          union
select '1782','1689'          union
select '1468','1782'          union
select '1316','1782'          union
select '1304','1782'          union
select '1101','1468'          union
select '1641','1468'          union
select '1641','1101'          union
select '1911','1247'          union
select '1501','1247'          union
select '1501','1911'          union
select '1934','1501'          union
select '1934','1316'          union
select '1304','1934'          union
select '1661','1304'          union
select '1025','1661'          ) x



select 
x.ID1 'A'
,x.ID2 'B'
, case when y.ID1 = z.ID1 then z.ID1
        when y.ID2 = z.ID2 then z.ID2
        when y.ID1 = z.ID2 then z.ID2
        when  y.ID2 = z.ID1 then z.ID1 end as 'C'
into #result

from 
(
select l.ID1,l.ID2
from #likes l
left join #Friend f
on l.ID1 = f.ID1
and l.ID2 = f.ID2
where f.ID1 is null ) x
join (


select x.*, y.ID1 lid1 from #Friend x
join (
select l.ID1
from #likes l
left join #Friend f
on l.ID1 = f.ID1
and l.ID2 = f.ID2
where f.ID1 is null 
union all 
select l.ID2
from #likes l
left join #Friend f
on l.ID1 = f.ID1
and l.ID2 = f.ID2
where f.ID1 is null 
)y
on x.ID1 = y.ID1) y
on x.ID1 = y.lid1

join (
select x.*,y.ID1 lid2 from #Friend x
 join
(
select l.ID1
from #likes l
left join #Friend f
on l.ID1 = f.ID1
and l.ID2 = f.ID2
where f.ID1 is null 
union all 
select l.ID2
from #likes l
left join #Friend f
on l.ID1 = f.ID1
and l.ID2 = f.ID2
where f.ID1 is null 
)y
on x.ID2 = y.ID1) z
on x.ID2 = z.lid2
where y.ID1 = z.ID1 or y.ID2 = z.ID2 or y.ID1 = z.ID2 or y.ID2 = z.ID1


select 
h1.*
,h2.*
,H3.*
from #result r
join #Highschooler h1
on r.A = h1.ID
join #Highschooler h2
on r.b = h2.ID
join #Highschooler h3
on r.c = h3.ID 

You can try the below query as well:

select * into #likes
from(
select '1689'ID1,'1709'ID2  union  
select '1709','1689'        union 
select '1782','1709'        union 
select '1911','1247'        union 
select '1247','1468'        union 
select '1641','1468'        union 
select '1316','1304'        union 
select '1501','1934'        union 
select '1934','1501'        union 
select '1025','1101')x

select * into #Highschooler
from (
select '1510'ID,'Jordan'name, 9 grade   union
select '1689','Gabriel', 9                          union
select '1381','Tiffany', 9                          union
select '1709','Cassandra', 9                        union
select '1101','Haley', 10                           union
select '1782','Andrew', 10                          union
select '1468','Kris', 10                            union
select '1641','Brittany', 10                        union
select '1247','Alexis', 11                          union
select '1316','Austin', 11                          union
select '1911','Gabriel', 11                         union
select '1501','Jessica', 11                         union
select '1304','Jordan', 12                          union
select '1025','John', 12                            union
select '1934','Kyle', 12                            union
select '1661','Logan', 12       ) x             


  select * into #Friend
  from(
select '1510'ID1,'1381'ID2    union
select '1510','1689'          union
select '1689','1709'          union
select '1381','1247'          union
select '1709','1247'          union
select '1689','1782'          union
select '1782','1468'          union
select '1782','1316'          union
select '1782','1304'          union
select '1468','1101'          union
select '1468','1641'          union
select '1101','1641'          union
select '1247','1911'          union
select '1247','1501'          union
select '1911','1501'          union
select '1501','1934'          union
select '1316','1934'          union
select '1934','1304'          union
select '1304','1661'          union
select '1661','1025'          union
select '1381','1510'          union
select '1689','1510'          union
select '1709','1689'          union
select '1247','1381'          union
select '1247','1709'          union
select '1782','1689'          union
select '1468','1782'          union
select '1316','1782'          union
select '1304','1782'          union
select '1101','1468'          union
select '1641','1468'          union
select '1641','1101'          union
select '1911','1247'          union
select '1501','1247'          union
select '1501','1911'          union
select '1934','1501'          union
select '1934','1316'          union
select '1304','1934'          union
select '1661','1304'          union
select '1025','1661'          ) x

--Select list of Likes which are not friends of each other
SELECT * INTO #IntermediateResults FROM #Likes l
WHERE NOT EXISTS (SELECT 1 FROM #Friend WHERE ID1 = l.ID1 AND ID2 = l.ID2)

--Select a distinct list of friends for each person in the above table.
SELECT DISTINCT Person,Friend INTO #PersonFriend FROM
(
SELECT F.ID1 AS Person, F.ID2 AS Friend 
FROM #Friend F
JOIN #IntermediateResults IR ON F.ID1 IN (IR.ID1 , IR.ID2)
UNION ALL

SELECT F.ID1 AS Person, F.ID2 AS Friend 
FROM #Friend F
JOIN #IntermediateResults IR ON F.ID2 IN (IR.ID1 , IR.ID2)
)aa

--Select those records where a friend of one person is the friend of another person as well.
SELECT 
    HS1.ID AS Person1ID, 
    HS1.Name AS Person1Name, 
    HS1.grade AS Person1Grade,

    HS2.ID AS Person2ID, 
    HS2.Name AS Person2Name, 
    HS2.grade AS Person2Grade,

    HS3.ID AS CommonFriendID, 
    HS3.Name AS CommonFriendName, 
    HS3.grade AS CommonFriendGrade
FROM 
    #IntermediateResults IR 
    JOIN #PersonFriend PersonFriend ON IR.ID1 = PersonFriend.Person
    JOIN #Highschooler HS1 ON IR.ID1 = HS1.ID
    JOIN #Highschooler HS2 ON IR.ID2 = HS2.ID
    JOIN #Highschooler HS3 ON PersonFriend.Friend = HS3.ID
WHERE 
    EXISTS (SELECT 1 FROM #IntermediateResults IR2 
              JOIN #PersonFriend PersonFriend1 ON IR2.ID2 = PersonFriend1.Person
              WHERE ID2 = IR.ID2 AND PersonFriend1.Friend = PersonFriend.Friend)
select h1.name, h1.grade, h2.name, h2.grade, h3.name, h3.grade 
from highschooler h1, 
     highschooler h2, 
     highschooler h3, 
     likes, 
     friend f1, 
     friend f2
where h1.id = likes.id1 
and h2.id = likes.id2 
and not exists (select * from Friend F where F.ID1 = H1.ID and F.ID2 = H2.ID)
and h3.id = f1.id2 
and h2.id = f2.id1 
and h3.id = f2.id2 
and h1.id = f1.id1 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM