Multiples SQL Joins - php

I have this problem and I haven't been able to figure out how can I make this work.
I have a table called "parents" and a table called "students"
Parents table has
id, name, lastname and type. "Type" cantains something like "mother" or "father".
Students table has
id, name, lastname, motherid(parents table), fatherid(parents table).
How can I make a query with JOINS that returns the Mother's name and the Father's name? And knowing that the parents can have multiple children, and obviously a student can have two parents, Mother and Father...
I hope I explained it well, thank you beforehand

This is the simple way to do what you're asking:
(
SELECT KIDS1.id as student_id
KIDS1.name as student_firstname
KIDS1.lastname as student_lastname
MOMS.id as parent_id
MOMS.name as parent_firstname
MOMS.lastname as parent_lastname
MOMS.type as parent_type
FROM students KIDS1
JOIN parents MOMS ON KIDS1.motherid = MOMS.id
)
UNION
(
SELECT KIDS2.id as student_id
KIDS2.name as student_firstname
KIDS2.lastname as student_lastname
DADS.id as parent_id
DADS.name as parent_firstname
DADS.lastname as parent_lastname
DADS.type as parent_type
FROM students KIDS2
JOIN parents DADS ON KIDS2.fatherid = DADS.id
)
I've updated my query now so that you can get a list of the parents and what kind of parent it is (mother or father). This query will not list students that don't have a parent listed in your system. You will have to modify or write a different query to determine which students do not have a parent listed.

You can do this with two Inner joins (not sure if this is the best way)
Your two joins would look something like:
Select students.name, parents.name
FROM students
INNER JOIN Parents
ON motherid = Parents.id
INNER JOIN Parents
ON fatherid = Parents.id

Related

join 2 tables through additional one MySQL/PHP

Let's say we have 2 tables
#film_info
[
movieID
movieValue1
movieValue2
]
#actor_info
[
actorID
actorValue1
actorValue2
]
and we also have
#film_actor
[movieID, actorID]
what i'm trying to do is to join those movie and actro via movie_actor, so that i can select a movie and see every actor, that stars in it.
$db->prepare("SELECT *
FROM film_info fi
INNER JOIN film_actor fa
ON fi.film_id = fa.film_id
INNER JOIN actor_info ai
ON fa.actor_id = ai.actor_id");
with something like this. It works, but gets me an array of all the film information for every actor thats stars in it. For example, if there's six actors it will return 6 arrays of same movie info, only having different [actor_name] every time.
Which stands a question: Is there any way to make it return one array with a list of all the actors? Or should i just write a function to manually pick all the actors from 6+ arrays?
Sorry for my terrible english and thanks in advance!
You should group by the movie, then group_concat the actors so they are all returned in the 1 movie row. You also can use using for the on when the columns of both tables have the same name. This should do what you are asking:
SELECT fi.movie_title, group_concat(actor_name_column)
FROM film_info fi
INNER JOIN film_actor using(film_id)
INNER JOIN actor_info using(actor_id)
group by film_id

Single query SELECT propagate to childs

i have this table structure:
id
name
email
child_id <- pointing to id from "child" table
how SELECT this table data and propagate select to all childs with a SINGLE QUERY?
If you assume you're working with a child table with its own name and id field, you could write...
select c.name as child_name, p.name as parent_name
from child c
join parent p
on c.id = p.child_id
I made a SQLFiddle with the following SQL:
CREATE TABLE "parent" (
"id" INTEGER PRIMARY KEY,
"name" TEXT,
"email" TEXT,
"child_id" INTEGER
);
CREATE TABLE "child" (
"id" INTEGER PRIMARY KEY,
"name" TEXT
);
INSERT INTO parent
(id, name, email, child_id )
VALUES
(1, "Jim", "pineapple#fruit.com", 1 ),
(2, "Jane", "gizmo#gadget.com", 1 ),
(3, "Grover", "monty#python.com", 2 );
INSERT INTO child
(id, name)
VALUES
(1, "Ben" ),
(2, "Samantha" ),
(3, "Carl" );
My select query then gave me:
However, this data structure limits you to only on child per parent though I showed 2 parents for one of the kids. If you want multiple of either without having to duplicate the parent entries, you'd want to have a third table for the parent child relationship. That Table would have a parent_id, a child_id, and there are different schools of thought on whether it having it's own id would be required (it makes selecting specific rows in the relationship table easy and becomes more important if the relationship gains additional fields itself). Your query would need to join all the tables to the relationship table and if you did this, that part might look something like this:
from relationship r
join parent p
on p.relation_id = r.parent_id
join child c
on c.relation_id = r.child_id

Left join with filter

I'm trying to display a list of books from a table (books) but I want to display the name of the book in green if the user connected added the book in his collection. The collections are in the table collection. So I need to retrieve all the informations from the books table but I need to differentiate the books owned by the user.
I tried something like this :
SELECT * FROM books LEFT JOIN collection ON books.ID = collection.ID_book AND collection.ID_member = :ID_member WHERE books.ID_author = :ID_author
:ID_member is the ID in session of the member logged in and ID_author is the name of the author I want to display the list. But with that query, I cannot retrieve the ID of books that the user doesn't own. Do you have an idea to retrieve these ID too ?
I thought of a second query inside the while() but that would means a query PER book...
EDIT (more informations) :
I have a table books with all the informations concerning the books.
Then, I have a table collection with these columns : ID, ID_member, ID_book
With my query, if I want to display all books from... let's say Stephen King, I have something like this :
book || ID of the book || book owned by the user
1 || 1 || 0
2 || 2 || 0
3 || || 1
4 || 4 || 0
5 || || 1
6 || 6 || 0
The ID I want to display is the collection.ID_book because if I display ID, it will show collection.ID
So as you can see when the user own the book I can't have the ID of the book... but I can display the other informations (like the book title) because the other informations are taken from the books table and the ID from the collection table... Too bad that it's not possible to chose the table in the
I understand that the problem is that the ID column exists in both tables. One solution may be to duplicate the ID column, like ID2. Then it will work because ID2 doesn't exist in the collection table. But that is maybe too much...
Thank you for your help.
Regards.
It is very easy to set columns up with aliases:
SELECT books.ID AS book_id, collections.id AS collection_id
FROM books
LEFT JOIN collection ON books.ID = collection.ID_book AND collection.ID_member = :ID_member
WHERE books.ID_author = :ID_author
After you have done this your column names will be book_id and collection_id and since they are no longer duplicate names (with one overwriting the other) you can access each of them.
Then if you know that you want all the columns from books but only the idcolumn from collection you can do something like this:
SELECT books.*, collections.id AS collection_id
FROM books
LEFT JOIN collection ON books.ID = collection.ID_book AND collection.ID_member = :ID_member
WHERE books.ID_author = :ID_author
I think your query should be doing what you want. I suspect that the problem may be the select * and multiple columns with the same name. Does this query do what you want?
SELECT b.*,
(case when c.ID_book is not null then 'GREEN' else 'NOT OWNED' end) as color
FROM books b LEFT JOIN
collection c
ON b.ID = c.ID_book AND c.ID_member = :ID_member
WHERE b.ID_author = :ID_author;
I think you can solve this problem by changing your query slightly, maybe give this a try.
SELECT * FROM books
LEFT JOIN collection ON books.ID = collection.ID_book
WHERE books.ID_author = :ID_author OR collection.ID_member = :ID_member
When joining on the condition of the user id, you're only going to have those rows available in the result set. By moving that condition to the WHERE clause using the OR operator, you can have both conditions met.
NOTE: Try not to use SELECT *.
SELECT * FROM books LEFT JOIN collection
ON books.ID = collection.ID_book
INNER JOIN member ON collection.ID_member = member.:ID_member WHERE books.ID_author = :ID_author
would you try that sir.. I'm not sure though. I'm assuming that the ID_member fields came from a member table.. and the ID_member to collection table is a foreign key..

pull data from two tables

I need to pull data from two tables, and it's a bit over my head :
The first tables contains a list of members (member_id, username, email ...)
The second table stores relations between members (id, member_id, friend_id)
When a member adds another member as a friend, both member_ids are stored in the second table.
Now I need to output that second table, I'd like to output usernames instead of numbers :
example :
{username corresponding to member_id} added {username corresponding to friend_id} as a friend
Can someone help with the query ?
You need to perform a double join on members
SELECT mem1.username, mem2.username
FROM members mem1
INNER JOIN relations
ON mem1.member_id = relations.member_id
INNER JOIN member mem2
ON relations.friend_id = mem2.member_id
Something like:
select tb1.username as member_name,
tb2.username as friend_name
from membertable as tb1
inner join
(
membertable as tb2,
memberrelationstable
)
on
(
tb1.member_id = memberrelationstable.member_id and
tb2.member_id = memberrelationstable.friend_id
)
This is how I would do it:
SELECT member.username AS member_username, friend.username AS friend_username
FROM relations
INNER JOIN members AS member
ON relations.member_id = member.member_id
INNER JOIN members AS friend
ON relations.friend_id = mem2.member_id
I've spaced it so that you can easily see how we're joining the members table twice, and simple giving it a different name both times.
Whenever something is followed by AS, it means that you're giving it another name. This allows you to use the same table multiple times in a single query.

Many to many relationship queries

I'm a bit confused about many to many relationship tables, and the code that goes with them.
I have table1:
id, username
And table2:
id, votes_up, votes_down
And a helper table (htable):
vu, vd, adsid
What I want to happen is, when an ad is voted up or down, this vote doesn't go to all adverts.
My attempt at selecting data:
mysql_query("SELECT *
FROM dbo.tab2
INNER JOIN dbo.htable
WHERE tab2.votes_up = htable.vu
AND htable.votes_down = htable.vd
INNER JOIN dbo.tab1
WHERE htable.adsID = table1.ID");
And my insert attempt:
mysql_query("INSERT INTO dbo.htable (vu, vd, adsid)
VALUES
(SELECT FROM dbo.tab2.votes_up, dbo.tab2.votes_down , dbo.tab1.id)");
My question: Are these two queries correct? If not, how can I fix them? and what is the update query ?
I do not really understand your question, but your SQL queries are wrong. They should probably be something like:
SELECT
*
FROM
dbo.tab2 as tab2
INNER JOIN dbo.htable as htable
ON tab2.votes_up = htable.vu
AND tab2.votes_down = htable.vd
INNER JOIN dbo.tab1 as tab1
ON htable.adsID = tab1.ID
and
INSERT INTO dbo.htable (vu, vd, adsID)
SELECT
votes_up, votes_down, ID
FROM
dbo.tab2

Categories