SQL: Join two different rows from the same table to a relation - sql

Let's say I've got a table called relation with these fields:
id, type, person1.id, person2.id
Then there's the table with the people called person with this field:
id, name
Now I want to create a list that contains the following information:
relation.id, relation.type, person1.id, person1.name, person2.id, person2.name
How can I achieve this with an SQL statement? I know that this is probably a pretty basic question. :-(

You need to use the person table twice:
select rel.id, rel.type, p1.id, p1.name, p2.id, p2.name
from relation rel
, person p1
, person p2
where rel.person1 = p1.id
and rel.person2 = p2.id
Take a look at this

select relation.type,a.Person1_name,b.person2.name from relation inner join
(select relation.type, person1.name Person1_name from relation inner join person
on relation.person1=person.name
where person1 is not null)a
on relation.type=a.type
inner join
(
select relation.type, person2.name,from relation inner join person
on relation.person2=person.name
where person2 is not null)b
on relation.type=a.type
pls try this code

Related

PostgreSQL: How do I get data from table `A` filtered by a column in table `B`

I want to fetch all parents that have kids in a specific grade only in a school.
Below are trimmed down version of the tables.
TABLE students
id,
last_name,
grade_id,
school_id
TABLE parents_students
parent_id,
student_id
TABLE parents
id,
last_name,
school_id
I tried the below query but it doesn't really work as expected. It rather fetches all parents in a school disregarding the grade. Any help is appreciated. Thank you.
SELECT DISTINCT
p.id,
p.last_name,
p.school_id,
st.school_id,
st.grade_id,
FROM parents p
INNER JOIN students st ON st.school_id = p.school_id
WHERE st.grade_id = 118
AND st.school_id = 6
GROUP BY p.id,st.grade_id,st.school_id;
I would think:
select p.*
from parents p
where exists (select 1
from parents_students ps join
students s
on ps.student_id = s.id
where ps.parent_id = p.id and
s.grade_id = 118 and
s.school_id = 6
);
Your question says that you want information about the parents. If so, I don't see why you are including redundant information about the school and grade (it is redundant because the where clause specifies exactly what those values are).

joining a table on 2 fields

I want to pull a person and their supervisor names from a table. The persons table has the supervisor_id and the person_id. The names table has name_id and a Full Name field. If I join Person ON either supervisor_id or person_id, how do I get the other to display as well?
You need to join twice, one for each relationship you have:
SELECT
-- Persons' columns
P.*,
-- Superviser name columns
SN.*,
-- Person name columns
PN.*
FROM
persons AS P
LEFT JOIN names AS SN ON P.supervisor_id = SN.name_id
LEFT JOIN names AS PN ON P.person_id = PN.name_id
Or you can join with an OR clause, but you won't be able to know which record did you join with unless you check with a CASE.
SELECT
-- Persons' columns
P.*,
-- name columns
N.*,
IsSupervisor = CASE WHEN P.supervisor_id = N.name_id THEN 'Yes' ELSE 'No' END
FROM
persons AS P
LEFT JOIN names AS N ON
P.supervisor_id = N.name_id OR
P.person_id = N.name_id
This last approach will display 2 rows as it will match either one or the other on different occasions, not both with the same persons row (as the first example).
A (self)join is what you need:
select p.*, supervisor=ps.name
from Person p join person ps on p.supervisor_id=ps.id

How do I do an SQL query based on a foreign key field?

I have the following tables:
people:
id, name
parent:
id, people_id, name
I have tried the following:
SELECT * FROM people
LEFT JOIN parent ON people.id = parent.people_id
WHERE parent.name != 'Carol';
How do I find all the people whose parent's name is not Carol?
You can try below code
select people.name from people
inner join parent on people.id=parent.people_id
where parent.name not in ('Carol')
If the two tables are to be queried by using Foreign Key.
If you want to get all records from one table that have some related entry in a second table then use Inner join
Select * from People INNER JOIN parent ON people.id = parent.people_id
WHERE parent.name <> 'Carol'
Similarly LEFT JOIN will get all records from the LEFT linked table but if you have selected some columns from the RIGHT table, if there is no related records, these columns will contain NULL
First of all, why would you need two tables? why can't you have a single table named "Person" with ID,Name,ParentID columns
Where ParentID will be optional and reference the ID if it has got parent.
And run the following query
select * from PERSON where Name not like 'Carol%' and ParentID IS NOT NULL;
SELECT * FROM people WHERE EXISTS(SELECT 1 FROM parent WHERE people_id = id AND name <> 'Carol')
First of all the table structure you have taken restrict the future growth. Like in future if you want to add parents of your parents then it wont work in this table structure.
You can do like :
id | parent_id | people_name
Here you can make parent_id null for the parent and add parent_id as id for those who have parent. Here to retrieve you have to use SELF join(join in the same table)
`
Select * from people P
INNER JOIN parent PA ON PA.people_id = P._id
where PA.name not in ('Carol')
`
Difference between INNER JOIN and LEFT OUTER JOIN
is
1) INNER JOIN bring only similar data between two table
for ex if in people table parent_id table is nullable then it will not discard the complete row,but in case of LEFT OUTER JOIN it will bring all the rows from LEFT table as well as related table from right table.with all null in right joined row..

How to show two columns of names?

SQL question
I have a table with Students (ID and Name)
I have another Table with Friends (ID1 and ID2)
create table Students(ID int, name text);
create table Friends(ID1 int, ID2 int);
If I enter:
SELECT Friends.ID1, Friends.ID2 FROM Friends
I get:
http://image.prntscr.com/image/d6e599ee5bd74c13822339afeb4c05ab.png
I think I need to use:
SELECT Strudets.Name
from Friends, Strudents
Where Strudents.ID=Friends.ID
And I want to show two columns of names
I need to look for the Friends.ID1 in the Students Table and get the Strudents.name, then do the same for Friends.ID2 and then show both names
EDIT with more info
When I enter this:
SELECT id1, name
FROM friends
INNER JOIN students
ON friends.id1 = students.id
I get this:
Lista de una sola columna
And I need to show two columns of names
ANSWER FROM #kbbal
SELECT s1.NAME, s2.NAME
FROM FRIENDS
INNER JOIN STUDENT s1 ON FRIENDS.ID1 = s1.ID
INNER JOIN STUDENT s2 ON FRIENDS.ID2 = s2.ID
I love this website!! <3
You seem new so I will lay out an approach.
Join the friends table to the students table. You should do this for the first friend first, so join the tables on the common ids. This would be the id column in the students table and id1 in the friends table.
Join the students table again. This time perform the join on id2 of the friends table
Specify that you want id1, name, id2, name in the SELECT statement
Your final answer should give you the ids of both friends and the names corresponding to their ids in the students table.
Edit based on comments:
Here is how you would do the joins:
SELECT friends.id1, s1.name, friends.id2, s2.name
FROM friends
INNER JOIN students s1
ON friends.id1 = s1.id
INNER JOIN students s2
ON friends id2 = s2.id
The trick is to actually join the students table twice, once for each friend. And then you just have to create aliases (s1 and s2) so you can distinguish between the two instances.

SQL query for finding row with same column values that was created most recently

If I have three columns in my MySQL table people, say id, name, created where name is a string and created is a timestamp.. what's the appropriate query for a scenario where I have 10 rows and each row has a record with a name. The names could have a unique id, but a similar name none the less. So you can have three Bob's, two Mary's, one Jack and 4 Phil's.
There is also a hobbies table with the columns id, hobby, person_id.
Basically I want a query that will do the following:
Return all of the people with zero hobbies, but only check by the latest distinct person created, if that makes sense. Meaning if there is a Bob person that was created yesterday, and one created today.. I only want to know if the Bob created today has zero hobbies. The one from yesterday is no longer relevant.
select pp.id
from people pp, (select name, max(created) from people group by name) p
where pp.name = p.name
and pp.created = p.created
and id not in ( select person_id from hobbies )
SELECT latest_person.* FROM (
SELECT p1.* FROM people p1
WHERE NOT EXISTS (
SELECT * FROM people p2
WHERE p1.name = p2.name AND p1.created < p2.created
)
) AS latest_person
LEFT OUTER JOIN hobbies h ON h.person_id = latest_person.id
WHERE h.id IS NULL;
Try This:
Select *
From people p
Where timeStamp =
(Select Max(timestamp)
From people
Where name = p.Name
And not exists
(Select * From hobbies
Where person_id = p.id))