Select from multiple tables where conditions must be met - php

I wanted to see if I can better organize / optimize my code, and so I've been reading more about joins and how you can query / select from two different tables where a certain column matches up in a single query. However, I could not find any documentation on what I would like to do.
Consider two tables (A , B).
Table A
user_id -- + -- course_id
1 -- + -- 1
Table B
course_id -- + -- project_id
1 -- + -- 2
My queries look something along the lines of the following:
$sql_course= mysql_query("SELECT course_id FROM A WHERE user_id = 1") or die(mysql_error());
while ($course_row = mysql_fetch_assoc($sql_course)) {
// Unique course ID
$courseID = $course_row['course_id'];
$sql_b= mysql_query("SELECT project_id FROM B WHERE course_id=$courseID") or die(mysql_error());
So, you see, this is not very easy to explain. I suppose what I'm looking to find out is whether or not there is a way to optimize this code, say, using one query?

Yes you can achieve this using joins in SQL.
Try something like this:
SELECT project_id FROM B JOIN A on B.course_id=A.course_id WHERE user_id=1
There are several types of joins, and depending on the results set you'll need to use different ones.
There is a good examination of what joins are doing here:
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

Try:
$sql_course = mysql_query("SELECT A.course_id, B.project_id FROM A INNER JOIN B ON B.course_id = A.course_id WHERE A.user_id = 1 ORDER BY A.course_id, B.project_id") or die(mysql_error());
You only need to include A.course_id in the select portion if you care about the value.

SELECT b.project_id
FROM table_b b
JOIN table_a a ON a.course_id = b.course_id
WHERE a.user_id = 1
Whether this will actually give you exactly what you want depends on what you are doing with the data, but hopefully it will give you a starting point.

You can use inner join to make it as single query. As I understood, you are trying to get project_id based on user_id and the user_id is 1.
There is a foreign key relation between Table A and B. So, you can write query as -
Select project_id from A, B where A.course_id = B.course_id and user_id = 1;

Related

MYSQL - Getting the value from a field in a lookup table and main table in the same query

I have 2 table which I will describe below:
1) The main table which has an auto increment by U_ID and has a column named RU_ID which refers to the ID of a lookup table.
2) The Lookup table is auto incremented by RU_ID and has a column named ROLE which has a sting value.
Now I am needing a SELECT statement that show me all the values of the main table (SELECT * FROM...) and the ROLE value of the lookup table.
I have this so far:
Note that the = 2 is static for this example only, this will be a variable which holds the RU_ID number. Also this example will be used in PHP - PDO, but the SQL query is generic really.
SELECT *
FROM tbl_users as u
WHERE u.RU_ID = 2
AND STATUS = 1
AND u.RU_ID IN
(SELECT ROLE
FROM tbl_role_users, tbl_users
WHERE RU_ID = 2)";
Thanks for looking into this with me.
have you tried a JOIN?
SELECT t.*, t1.role
FROM tbl_users t
JOIN tbl_role_users t1 ON t.RU_ID = t1.RU_ID -- # --or t1.ID whichever is referenced
WHERE t1.RU_ID = 2
AND t.status = 1;
if you want to join the table without filtering excess rows then just add LEFT before the JOIN
Note:
I would recommend you steer away from the pre ANSI way of joining tables and actually use the JOIN syntax as its easier to read in complicated queries and or you can have more functionality with the JOIN syntax.. and that way you dont need the IN() statement

SQL Optimization WHERE vs JOIN

I am using mysql and this is a query that I quickly wrote, but I feel this can be optimized using JOINS. This is an example btw.
users table:
id user_name first_name last_name email password
1 bobyxl Bob Cox bob#gmail.com pass
player table
id role player_name user_id server_id racial_name
3 0 boby123 1 2 Klingon
1 1 example 2 2 Race
2 0 boby2 1 1 Klingon
SQL
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`,`users`
WHERE `users`.`id` = 1
and `users`.`id` = `player`.`user_id`
I know I can use a left join but what are the benefits
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`
LEFT JOIN `users`
ON `users`.`id` = `player`.`user_id`
WHERE `users`.`id` = 1
What are the benefits, I get the same results ether way.
Your query has a JOIN in it. It is the same as writing:
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`
INNER JOIN `users` ON `users`.`id` = `player`.`user_id`
WHERE `users`.`id` = 1
The only reason for you to use left join is if you want to get data from player table even when you don't have matches in users table.
LEFT JOIN will get data from the left table even if there's no equal data from the right side table.
I guess at one point, that player table's data will not be equivalent to users table specially if the data on users table has not been inserted into player table.
Your first query might return null on cases that the 2nd table (player) has no equivalent data corresponding to users table.
Also, IMHO, setting up another table for servers is a good idea in terms of complying to the normalization rules in database structure. After all, what details of the server_id is the column on player table pointing to.
The first solution makes a direct product (gets and connects everything with everything) then drops away the bad results. If you have a lot of rows this will be very slow!
The left join gets first the left table then put only the matching rows from the right (or null).
In your example you don't even need join. :)
This'll give you the same result and it'll be good until you just check for user id:
SELECT `player`.`server_id`,`player`.`id`,`player`.`player_name`,`player`.`racial_name`
FROM `player`
WHERE `player`.`user_id` = 1
Another solution if you want more conditions, without join could be something like this:
SELECT * FROM player WHERE player.user_id IN (SELECT id FROM user WHERE ...... )

Struggling with SQL

I have two table in the same database: hlstats_Events_Connects and hlstats_PlayerUniqueIds.
In the hlstats_Events_Connects I have a value I wish to get, however the ID it's related to I need to get from the data in another table, using the "uniqueId" that I have. Example:
**hlstats_Events_Connects**
playerId eventTime
----------------------
8 2013-04-05 05:44:14
**hlstats_PlayerUniqueIds**
playerId uniqueId
---------------------
8 0:0:84901
So I have the "uniqueId" as a variable, and I want to say, get the playerId of the persons uniqueId, then get the eventTime from what the playerId is. Currently I have something along the lines of the below, but can't figure out the Where clause.
SELECT c.eventTime, c.playerId, u.uniqueId, u.playerId
FROM c.hlstats_Events_Connects, u.hlstats_PlayerUniqueIds
WHERE ...?
Cheers
Looks like you are just missing the JOIN. You will join the tables on the playerId column:
SELECT c.eventTime, c.playerId, u.uniqueId, u.playerId
FROM c.hlstats_Events_Connects c
INNER JOIN u.hlstats_PlayerUniqueIds u
ON c.playerId = u.playerId
Note, I updated the query to use ANSI JOIN syntax, in this case an INNER JOIN. This is standard SQL syntax, instead of commas between the tables and the join in the WHERE
Use JOIN like this
SELECT c.eventTime, c.playerId, u.uniqueId, u.playerId
FROM c.hlstats_Events_Connects, u.hlstats_PlayerUniqueIds
WHERE c.playerId = u.playerId
You don't need to add prefixes to table names, instead those should be specified after table name, and also you can just join on playerId column (if those are large tables, I'd suggest adding an index to those columns.)
SELECT
c.eventTime, c.playerId, u.uniqueId, u.playerId
FROM
hlstats_Events_Connects c,
hlstats_PlayerUniqueIds u
WHERE
u.uniqueId = "0:0:84901" and
u.playerId = c.playerId

Retrieve a value through three tables in a single Query

I have been trying to understand joins for a while now, I've noticed quite a few examples showing how to retrieve a value based on a two-table query using a left / inner join. I will try to draw out my example for you all, hopefully it will aid in the explanation of my question.
Table 1:
project_id | project_name
1 super-project
Table 2:
project_id | course_id ---> project_id and course_id are foreign keys here.
1 3
Table 3:
course_id | course_name ---> course_id is a primary key here
3 | Writing 101
My Goal:
I would like to be able to return "Writing 101" by using the project_id. So, if I know the project_id is 1, I would query the db to find that the course_id associated with the current project is 3. I would then use the course_id of 3 to query table 3 and find that the related course_name is writing 101.
Is there a way to do this in a single query using join of some sort?
select course_name from Table3
inner join Table2
on Table2.course_id = Table3.course_id
where Table2.project_id = 1
Notice there is only 1 join needed!
Also note that if the project_id = 1 is present in more than one course all of those courses will appear.
Can you explain why only one join is needed as opposed to the answer below which requires two joins?
The other answer does not require two joins. As the project_id is present in the "middle" table there is no need to look for it in Table1. Now, if you require the name of the project (which is not the case because you didn't mention that in the question) then you would have to join the Table1
Here you go:
SELECT c.course_name
FROM Table3 c
INNER JOIN Table2 pc ON pc.course_id = c.course_id
INNER JOIN Table1 p ON p.project_id = pc.project_id
WHERE project_id = 1

MySQL join and exclude?

I have two tables, table A one with two columns: IP and ID, and table B with columns: ID and extra information. I want to extract the rows in table B for IPs that are not in table A. So if I have a rows in table A with
id = 1
ip = 000.000.00
id = 2
ip = 111.111.11
and I have rows in table B
id = 1
id = 2
then, given ip = 111.111.11, how can I return row 1 in table B?
select b.id, b.*
from b
left join a on a.id = b.id
where a.id is null
This'll pull all the rows in B that have no matching rows in A. You can add a specific IP into the where clause if you want to try for just that one ip.
The simplest and most easy-to-read way to spell what you're describing is:
SELECT * FROM `B` WHERE `ID` NOT IN (SELECT `ID` FROM `A`)
You should be aware, though, that using a subquery for something like this has historically been slower than doing the same thing with a self-join, because it is easier to optimise the latter, which might look like this:
SELECT
`B`.*
FROM
`B`
LEFT JOIN
`A` ON `A`.`ID` = `B`.`ID`
WHERE
`A`.`ID` IS NULL
However, technology is improving all the time, and the extent to which this is true (or even whether this is true) depends on the database software you're using.
You should test both approaches then settle on the best balance of readability and performance for your use case.

Categories