Comparing values of columns from 3 tables - MySQL - php

following question:
I'm working with 3 tables = actors, movies, roles. I'm trying to find all the movies a given actor, say 'Robin Williams' has been in by comparing the specific actor id since there be may more than one actor with the same name. The actors table has the following relevant columns: first_name, last_name, id - the movies table has columns: id (the movie's id) - and the roles table has: actor_id and movie_id.
Do I JOIN the tables or use UNION? How do I compare columns from different tables when the columns have different names?
Thank you!
Just for reference:
Table actors:
mysql> SELECT *
-> FROM actors;
+--------+--------------------+------------------------+--------+------------+
| id | first_name | last_name | gender | film_count |
+--------+--------------------+------------------------+--------+------------+
| 933 | Lewis | Abernathy | M | 1 |
| 2547 | Andrew | Adamson | M | 1 |
| 2700 | William | Addy | M | 1 |
Table movies:
mysql> SELECT *
-> FROM movies;
+--------+------------------------------+------+------+
| id | name | year | rank |
+--------+------------------------------+------+------+
| 10920 | Aliens | 1986 | 8.2 |
| 17173 | Animal House | 1978 | 7.5 |
| 18979 | Apollo 13 | 1995 | 7.5 |
Table roles:
mysql> SELECT *
-> FROM roles;
+----------+----------+-------------------------------+
| actor_id | movie_id | role |
+----------+----------+-------------------------------+
| 16844 | 10920 | Lydecker |
| 36641 | 10920 | Russ Jorden |
| 42278 | 10920 | Cpl. Dwayne Hicks |
At first I tried setting each check equal to a PHP variable and comparing them but that seemed wrong, then I tried:
mysql> SELECT roles.actor_id, roles.movie_id, movies.id, actors.id
-> FROM roles
-> JOIN movies, actors
-> ON roles.actor_id = actors.id && roles.movie_id =movies.id;
which again does not work.

Finally figured it out..
>SELECT m.name, m.year
-> FROM movies m
->JOIN roles r ON m.id = r.movie_id
->JOIN actors a ON a.id = r.actor_id
->WHERE a.first_name = "whatever actor's first name"
->AND a.last_name = "whatever actor's last name"
This will then give you two columns with the corresponding name and year! hazzah!

First Read this answer - it made it click for me finally after years of unions when should join and vice versa.
In this case you should definitely JOIN as you want the result to act as a single row.
(think of it like this - I want to see Movie, Actor -> together as one result)
PS
You don't need your film count field any more as once you have the joins worked out you can just use MySQL COUNT -> it will make it easier to maintain.

You need a join. Try this:
SELECT A.first_name,A.last_name,A.gender,M.name,M.year,M.rank,R.role
FROM roles R INNER JOIN
Movies M ON R.movie_id = M.movie_id INNER JOIN
Actors A ON R.actory_id = A.id

Related

MySQL - inner join - add column with value based on other value

I'm struggling with mysql joins :/
I've multiple tables inside database fe. tasks, users etc.
Table tasks containing tasks with various variables, but the most important - id's of users signed to task (as different roles inside the task - author, graphic, corrector):
+---------+-------------+--------------+
| task_id | task_author | task_graphic |
+---------+-------------+--------------+
| 444 | 1 | 2 |
+---------+-------------+--------------+
Table users
+---------+----------------+------------+-----------+
| user_id | user_nice_name | user_login | user_role |
+---------+----------------+------------+-----------+
| 1 | Nice Name #1 | login1 | 0 |
+---------+----------------+------------+-----------+
| 2 | Bad Name #2 | login2 | 1 |
+---------+----------------+------------+-----------+
Using PDO I'm getting the whole data I want while using INNER JOIN with data from different tables (and $_GET variable)
SELECT tasks.*, types.types_name, warehouse.warehouse_id, warehouse.warehouse_code, warehouse.warehouse_description
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
INNER JOIN warehouse ON warehouse.warehouse_id = tasks.task_id
WHERE tasks.task_id = '".$get_id."'
ORDER BY tasks.task_id
Above query returns:
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
| task_id | task_creator | task_graphic | task_purchaser | task_title | task_lang | task_description | task_description_files | task_files | task_status | task_prod_index | task_type | task_print_run | task_print_company | task_warehouse_code | task_cost | task_time_added | task_deadline | task_date_warehouse |
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
| 2 | 1 | 2 | 1 | Test | PL | Lorem ipsum (?) | | | w | 2222 | 3 | 456546 | Firma XYZ | 2 | 124 | 29.09.2016 15:48:20 | 01.10.2016 12:00 | 07.10.2016 14:00 |
+---------+--------------+--------------+----------------+------------+-----------+------------------+------------------------+------------+-------------+-----------------+-----------+----------------+--------------------+---------------------+-----------+---------------------+------------------+---------------------+
And I'd like to get query with added user_nice_name after task_creator, task_author and task_graphic - obviously nice names selected from table users based on ID's provide in 3 above fields fe.
+---------+--------------+------------------------------------+--------------+--------------------------------------+
| task_id | task_creator | task_creator_nn | task_graphic | task_graphic |
+---------+--------------+------------------------------------+--------------+--------------------------------------+
| 2 | 1 | Nice Name (from task_creator ID=1) | 2 | Nice Name (from task_graphic ID = 2) |
+---------+--------------+------------------------------------+--------------+--------------------------------------+
How can I achieve that?
You need three joins:
SELECT t.*,
uc.user_nice_name as creator_name,
ug.user_nice_name as graphic_name,
up.user_nice_name as purchaser_name,
ty.types_name, w.warehouse_id, w.warehouse_code, w.warehouse_description
FROM tasks t INNER JOIN
types ty
ON ty.types_id = t.task_id INNER JOIN
warehouse w
ON w.warehouse_id = t.task_id LEFT JOIN
users uc
ON uc.user_id = t.task_creator LEFT JOIN
users ug
ON ug.user_id = t.task_graphic LEFT JOIN
users up
ON up.user_id = t.task_purchaser
WHERE t.task_id = '".$get_id."'
ORDER BY t.task_id;
Notes:
Table aliases make the query easier to write and to read. They are also required because you have three references to users in the FROM clause.
This uses LEFT JOIN for the users in case some of the reference values are missing.
You need to work on your naming. It doesn't make sense that a "warehouse" id matches a "task" id. Or that a "task" id matches a "types" id. But that is how you phrased the query in your question.
The ORDER BY effectively does nothing, because all rows have the same task_id.
Assuming that the task_graphic_name is inside a table name task_graphic_table and the relation field are task_graphic_id
SELECT tasks.*
, types.types_name
, warehouse.warehouse_id
, warehouse.warehouse_code
, warehouse.warehouse_description
, users.user_nice_name
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
INNER JOIN warehouse ON warehouse.warehouse_id = tasks.task_id
INNER JOIN users ON users.user_nice_name = tasks.task_graphic
WHERE tasks.task_id = '".$get_id."'
ORDER BY tasks.task_id
And if you need the column appear in a specific order you should explicitally call the column name in sequence eg:
SELECT tasks.col1
, task.col2
, types.types_name
, warehouse.warehouse_id
, warehouse.warehouse_code
, task.col2
, warehouse.warehouse_description
, task_graphic_table.task_graphic_name
Add two sub query in with your query. like
SELECT tasks.*,
....
....,
(select user_nice_name from users where id = tasks.task_author) AS task_creator_name,
(select user_nice_name from users where id = tasks.task_graphic) AS task_graphic_name
FROM tasks
INNER JOIN types ON types.types_id = tasks.task_id
....
....

Can this be done in a single query?

I have 3 tables in my database, in which team1 and team2 ids in Matches Table are equal to team_id in TeamNames Table.
also group in Matches Table is equal to group_id in GroupNames Table
Matches Table
-----------------------------------
| team1 | team2 | group | count |
| 3 | 5 | 1 | 1 |
| 1 | 2 | 3 | 0 |
-----------------------------------
GroupNames Table
-----------------------
| group_id | name |
| 1 | Finals |
| 3 | Semi-Final |
-----------------------
TeamName Table
-----------------------
| team_id | name |
| 5 | Flowers |
| 2 | Rainbow |
-----------------------
What I need to get is:
SELECT team1 , team1_name , team2 , team2_name , group , group_name WHERE count=1
I tried joining tables, but as each of the team1 and team2 should be related to unique id in TeamName Table I failed, getting group name was easy, but I failed getting all the above in single query
Questions:
Is this possible in single query?
Can this be done using CodeIgniter's "Active Record Class"?
Answer for q1:yes
Answer for q2:yes
Hope this may help you
$this->db->from('Matches m');
$this->db->select('m.team1,m.team2,m.group,m.count,tn1.name team1_name,tn2.name team2_name,gn.name group_name');
$this->db->join('TeamName tn1','tn1.team_id = m.team1');
$this->db->join('TeamName tn2','tn2.team_id = m.team2');
$this->db->join('GroupNames gn','gn.group_id = m.group');
$this->db->where('m.count',1);
$results=$this->db->get()->result();
yes. with INNER JOIN.
Here is an example to combine your three tables, if you want you can combine more.
SELECT * FROM matches ma INNER JOIN groups gr ON ma.groupid = gr.groupid INNER JOIN teams te ON ma.teamid = te.teamid WHERE ma.count = 1
Good luck!
Martin

How to merge to MySQL tables based on id

Let's say I have three tables like these:
table name:
id | name
1 | Bob
2 | Alice
3 | Bryan
etc
table pants:
id | size
1 | S
3 | M
table skirt:
id | size
2 | M
How do I merge the three tables using MySQL and obtain a table like this:
result table:
id | name | pants | skirt
1 | Bob | S |
2 | Alice| | M
3 | Bryan| M |
When there's no matching id, the cell will just be blank.
Join the tables with a left join. Like this:
SELECT
tablename.id,
tablename.name,
tablepants.size AS pants,
tableskirt.size as skirt
FROM
tablename
LEFT JOIN tablepants
on tablename.id=tablepants.id
LEFT JOIN tableskirt
ON tablename.id=tableskirt.id

JOIN rows from 3 tables WHERE tableA.column1 = tableB.column1 = tableC.column1

I have 3 tables, structured like so:
TABLE A:
ID | PCID | ACTIVE | COHORT | WEEKLY_MEETING_TIME | FYE_ID | RC | AGREEMENT_SIGNED | RELEASE_SIGNED | NOTES | FACULTY_ADVISOR
TABLE B:
ID | QUARTER | OFFICE | WRITING_CENTER | etc.. | etc.. | etc.. |
TABLE C:
ID | QUARTER | WEEK | EMAIL | etc.. | etc.. | etc.. |
The common element between all 3 tables is the ID field.
I need to SELECT from all 3 tables, and have each row represent one ID and all the values associated with that ID.
So, for example, each output row should look like a combination of the three tables:
RESULTS:
ID | PCID | ACTIVE | COHORT | WEEKLY_MEETING_TIME | FYE_ID | RC | AGREEMENT_SIGNED | RELEASE_SIGNED | NOTES | FACULTY_ADVISOR | QUARTER | OFFICE | WRITING_CENTER | etc.. | etc.. | etc.. | WEEK | EMAIL | etc.. | etc.. | etc.. |
I have no idea how to structure a query like this. I suspect it involves using JOINs but my attempts have proved futile.
how can I combine the data from 3 tables, based on shared ID field?
SELECT * FROM TABLEA
INNER JOIN TABLEB ON TABLEA.ID = TABLEB.ID
INNER JOIN TABLEC ON TABLEA.ID = TABLEC.ID
If you don't need all the values substitute the "*" with the names of the fields you need (ex. TABLEA.ID, TABLEB.QUARTER, TABLEC.WEEK...)
NATURAL JOIN works in MySQL:
select * from A natural join B natural join C
Try this :
SELECT / WHAT YOU NEED TO SELECT - NOT * !!!/
FROM TABLEA
INNER JOIN TABLEB USING (ID)
INNER JOIN TABLEC USING (ID)

MYSQL Joins to retrieve result

I will try to be as explanatory as possible regarding my question. I am using MYSQL/PHP to fetch data from two tables with the structure looking like the following:
table A
+---------+------------+
| userid | username |
+---------+------------+
| 1 | john |
| 2 | doe |
| 3 | lewis |
+---------+------------+
table B
+---------+------------+-----------+
| id |from_userid | to_userid |
+---------+------------+-----------+
| 1 | 1 | 3 |
| 2 | 3 | 2 |
| 3 | 1 | 2 |
| 4 | 2 | 1 |
+---------+------------+-----------+
Am trying to achieve the following:
+---------+------------+----------------------+
| id |sender username| receiver username |
+---------+------------+----------------------+
| 1 | john | lewis |
| 2 | lewis | doe |
| 3 | john | doe |
| 4 | doe | john |
+---------+------------+----------------------+
As you can see, instead of returning the sender or receiver user id, I am returning their username according to Table A.
can I use left or right joins in this scenario? Thanks in advance
Try this
SELECT b.id, sender.username AS sender_username, receiver.username AS receiver_username
FROM tableB AS b
JOIN tableA AS sender ON b.from_userid = sender.userid
JOIN tableA AS receiver ON b.to_userid = receiver.userid
Inner joins would work fine, you just need to do two of them...
Left and right joins are only needed when you want to get all records from one table and some from another table. In this case you have two distinct relationships thus the need for two joins. My MySQL skills are a bit rusty so I don't know if ' or [ are used as separators on the table/field names with spaces.
Select t1.ID, T1.userName as 'Sender userName', T2.username as 'Receiver username'
FROM [Table A] A
INNER JOIN [Table B] T1
on T1.from_userid = A.userID
INNER JOIN [Table B] T2
on T2.to_userid = A.userID

Categories