Advanced multiple join for mysql - php

So I have a query that gives me three numbers, I then want to look up these numbers from another table and get the name and url associated with them.
So I have a products table that i query, and that provides me these three numbers, but as there are 3 numbers, an inner join wouldnt work.
So I am essentially just trying to look up the name and url, of 3 numbers from the same table, and wondering how the most efficient way to achieve this would be.
$qry = mysqli_query($this->con,"SELECT * FROM products WHERE product_id=$this->id");
$row = mysqli_fetch_assoc($qry);
$main = $row['main_id'];
$cat = $row['categories_id'];
$sub = $row['sub_cat_id'];
So I can do a query for each number individually, but then that is a total of 4 queries. I was wondering if this could be done in just one, or possibly even 2.

Hard to say for sure without seeing some table structure and sample data, but something like this may work (where othertable is the name of the other table you are pulling urls and names from):
select p.mail_id,
p.categories_id,
p.sub_cat_id,
o1.url mail_id_url,
o1.name mail_id_name,
o2.url categories_id_url,
o2.name categories_id_name,
o3.url sub_cat_id_url,
o3.name sub_cat_id_name
from products p
join othertable o1 on o1.mail_id = p.mail_id
join othertable o2 on o2.categories_id = p.categories_id
join othertable o3 on o3.sub_cat_id = p.sub_cat_id
where p.product_id = $this->id
This assumes that a record exits in othertable for every id that you are looking up.

Related

Distinct Values from MySQLi Query

I am trying to only show unique userIds (userIds are (0,1,2,3,4,5,6,7,8,9 etc...) for the query I am running. I tried using DISTINCT in my query, but it only shows me unique values of the rows that have 2 or more of the same userId.
Is there a way I can use php to only show the unique values. My weak points are arrays and it makes it more complicated because its using data from a MySQLi query.
Example right now I have with the query now (lets say its GROUP BY rentPaid DESC and the rent total is 800.00 for all users):
userID rentPaid rentMonth
2--------800.00------April
1--------500.00------April
3--------400.00------April
3--------400.00------April
1--------200.00------April
1--------100.00------April
Example desired output:
userID rentPaid rentMonth
2--------800.00------April
1--------500.00------April
3--------400.00------April
Can I do this with MYSQL because I tried DISTINCT and it wouldn't work, how about PHP?
Query:
SELECT
properties.*,
leases.*,
users.userId, users.primaryPhone,
CONCAT(users.userFirstName,' ',users.userLastName) AS user,
admins.adminName, payments.*
FROM
properties
LEFT JOIN leases ON properties.propertyId = leases.propertyId
LEFT JOIN assigned ON properties.propertyId = assigned.propertyId
LEFT JOIN admins ON assigned.adminId = admins.adminId
LEFT JOIN users ON properties.propertyId = users.propertyId
LEFT JOIN payments ON properties.propertyId = payments.propertyId
WHERE
payments.rentMonth = '$currentMonth' AND
payments.rentYear = '$currentYear'
Edit: Please excuse my formatting, this is my first post.
Edit: Added query....its long, but works lol. I only want unique userIds (no double or triple userIds etc...)
I suspect this is what you want:
SELECT userID, MAX(rentPaid) AS maxRentPaid, rentMonth
FROM yourTable
WHERE rentMonth = "April"
GROUP BY userID
ORDER BY maxRentPaid

Assistance with MySQL left outer join and differentiating query results from same key

I am trying to learn about SQL joins and trying to apply them to an application I am building. I am doing a query to find a "game record" on a schedule based on a specific game id. But on this game record; for the "h_team" and the "v_team"; only the ids of the teams are on the game record. And so what I want to do is join the "teams" table and look up the two different team_names of the "h_team" and "v_team". I have it also pull in a "division name" as well using a join since only the division id is stored on the game record. I have gotten this all to work fine; except I do not know how to get the results separately for the "team_name" for h_team and v_team. Basically the key for each one is just "team_name"; I will paste in my code and then explain further:
$array_game_id6=32;
$sql = "SELECT * FROM playoff_schedule LEFT OUTER JOIN teams on playoff_schedule.h_team = teams.team_id || playoff_schedule.v_team = teams.team_id LEFT OUTER JOIN playoff_divisions on playoff_schedule.po_div_id = playoff_divisions.po_div_id WHERE tom_game_id=$array_game_id6";
foreach ($dbh->query($sql) as $resultsg39)
{
$h_team=$resultsg39[h_team];
$v_team=$resultsg39[v_team];
$po_div_id=$resultsg39[po_div_id];
$round=$resultsg39[round];
$game_id=$resultsg39[game_id];
$date=$resultsg39[date];
$timestamp=$resultsg39[timestamp];
$h_score=$resultsg39[h_score];
$v_score=$resultsg39[v_score];
$tom_game_id=$resultsg39[tom_game_id];
$h_name=$resultsg39[team_name];
$div_name=$resultsg39[playoff_name];
}
the problem comes in when i am trying to get the results of the query and store them all in the different variables…
the last two "$h_name" and "$div_name" are being pulled from the JOINs all the prior ones are on the game record itself…
what I want to do is store both the names from "v_team" and "h_team" in the respective variables $h_name and $v_name;
I have it storing the $h_name no problem; but i do not know how to make it store both $h_name and $v_name separately as they are both values in the column "team_name" from "teams" table. So I just need to somehow make it so when i get my results it can tell the difference between the two different "team_names" and I can store them in the two different variables…
If this is not clear please let me know.
Thanks!
***** UPDATE 10:49pm EST 2/5/2015
have made some progress on this but my query is not working; I think it is a problem with the aliases and such are not right; here is my non-working query as it is right now:
$sth = $dbh->prepare("SELECT home_team.team_name as home_team_name, visiting_team.team_name as visiting_team_name,
h_team, v_team, po_div_id, round, game_id, date, timestamp, h_score, v_score, tom_game_id, playoff_name FROM playoff_schedule
LEFT OUTER JOIN teams as home_team on playoff_schedule.h_team = teams.team_id
LEFT OUTER JOIN teams as visiting_team on playoff_schedule.v_team = teams.team_id
LEFT OUTER JOIN playoff_divisions on playoff_schedule.po_div_id = playoff_divisions.po_div_id
WHERE tom_game_id=$array_game_id6");
$sth->execute();
$article_list = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach ($article_list as $row => $link) {
$h_team=$link['h_team'];
$v_team=$link['v_team'];
$po_div_id=$link['po_div_id'];
$round=$link['round'];
}
if anyone can spot a problem with my new query I would really appreciate it!
I think what you are trying to do is:
select home_team.team_name as home_team_name,
visiting_team.team_name as visiting_team_name
from playoff_schedule
join team as home_team on playoff_schedule.h_team = teams.team_id
join team as visiting_team on playoff_schedule.v_team = teams.team_id
You can join to the same table as many times as you want to. In this case, it makes sense, because you really are trying to get two different bits of information.
Based on your last edit, the following query appears to work:
SELECT home_team.team_name AS home_team_name,
visiting_team.team_name AS visiting_team_name,
h_team,
v_team,
playoff_schedule.po_div_id,
round,
game_id,
date,
timestamp,
h_score,
v_score,
tom_game_id,
playoff_name
FROM playoff_schedule
LEFT OUTER JOIN teams AS home_team
ON playoff_schedule.h_team = home_team.team_id
LEFT OUTER JOIN teams AS visiting_team
ON playoff_schedule.v_team = visiting_team.team_id
LEFT OUTER JOIN playoff_divisions
ON playoff_schedule.po_div_id = playoff_divisions.po_div_id
WHERE tom_game_id=$array_game_id6
You can check the query and the schema at: SQLFiddle
A couple of thing that might be happening:
Is the query itself running?
What happens if you run the query in a mySQL client?
Are there any PHP errors in your log?
Could you post the schema itself?
Is $array_game_id6 actually an array of values? In that case, you need to use "in" as opposed to "=" in your where clause.
With regard to your updated query, I think the main thing you are missing is using the aliases in your JOIN conditions. You should keep your table aliases consistent throughout your query. Also, IMO its better to keep table aliases short so they are easier to read:
So applying those things to your query:
SELECT h.team_name as h_team_name, v.team_name as v_team_name, s.h_team, s.v_team, s.po_div_id, s.round, s.game_id, s.date, s.timestamp, s.h_score, s.v_score, s.tom_game_id, s.playoff_name
FROM playoff_schedule s
LEFT OUTER JOIN teams h ON (
s.h_team = h.team_id
)
LEFT OUTER JOIN teams as v ON (
s.v_team = v.team_id
)
LEFT OUTER JOIN playoff_divisions d ON (
s.po_div_id = d.po_div_id
)
WHERE s.tom_game_id = ?
Now I'm not 100% sure of your schema so I may have referenced some of the columns to the wrong table but you should be able to sort that out.

Better way to do this subquery

Let's say I have this query:
<?
$qi = $db->prepare('SELECT one.id, one.Value, two.Name, three.nfid, temp.Name AS Alias
FROM one
INNER JOIN two ON one.fid = two.id
LEFT OUTER JOIN three ON two.fid = three.fid
LEFT OUTER JOIN (SELECT id,Name FROM two) AS temp ON three.nfid = temp.id
WHERE one.rid = ?
ORDER BY one.id ASC');
$qi->execute( array( $id ) );
?>
Connections between the tables are:
Table one contains a number of rows with the fields one.Value, one.rid and one.fid.
fid is a connection to table two which contains the two.Name of the items (one.fid = two.id).
But sometimes the item is an alias for another item, which is why table three exists. It contains the fields three.fid and three.newfid where three.newfid = two.id (but for another item with another two.Name)
The query is supposed to fetch all rows from one with a certain one.rid and get one.Value, two.Name and if there is an three.fid for this one.fid, get two.Name for three.newfid and call it Alias.
Is there a way to improve this query or solve the problem in another way? Perhaps reshape the layout of the database? It is currently quite slow. The example here have been simplified to make it more general.
Thank you.
The subquery in parentheses forces MYSQL to ignore its indexes, which makes it take a long time. Better to directly join two as temp. As long as you always put two.[field] and temp.[field], it will tell them apart just fine.
SELECT one.id, one.Value, two.Name, three.nfid, temp.Name AS Alias
FROM one
INNER JOIN two ON one.fid = two.id
LEFT OUTER JOIN three ON two.fid = three.fid
LEFT OUTER JOIN two AS temp ON three.nfid = temp.id
WHERE one.rid = ?
ORDER BY one.id ASC

php/mysql/ajax join in query and accessing resulting variables

I have a query of a mysql database that joins two tables. In the first table it just pulls records based on an id. For the second table, there may or may not be matches based on a value in the first table. I want to get matches if there are any, otherwise, presumably those values of the resulting record set are empty.
The query seems to produce the right number of records. However, when I try to access values of some variables that should be present, I am not getting anything, either because I may be calling them the wrong name or they are not in recordset somehow. I am a bit fuzzy on mysql queries so would greatly appreciate any advice..
Table 1 parks
id | name | stateid
Table 2 parksvisited
id | visited | parkid | userid
PHP script
$sql = "SELECT *
FROM `parks` p
LEFT JOIN `parksvisited` pv
ON p.id = pv.parkid
WHERE p.stateid = '44'"
run query...
while($row = mysql_fetch_array($res))
{
if ($row['visited'] == 1) {
$visited = 1; }
else {
$visited = 0; }
Visited
}
Basically, I get stateid but I am not getting p.id or visited. It could be I am naming them wrong or possibly they are getting left out of results somehow... Thanks for any suggestions.
p.id is probably missing because each of p.id and pv.id are going to get returned as id, not as p.id or pv.id. Try this instead:
SELECT p.id pid,
p.*,
pv.id pvid,
pv.*
FROM `parks` p
LEFT JOIN `parksvisited` pv
ON p.id = pv.parkid
WHERE p.stateid = '44'
It also doesn't look like you're selecting anything from pv in your original query, just p. See if this new query takes care of visited as well. And make sure to refer to pid as $row['pid'], not $row['p.id'].

SQL Advice - selecting multiple rows from a table as an innerJoin

I've been working on a project that until now has only needed to find 1 row from the joined table. But now I need to grab multiple rows..
So as it stand my sql works something like:
Select rows for each company for this particular project which alone would find company details (name, id, telephone.. blah).
Then I join a table that contains form data submitted for each company (multiple forms - so multiple records)
Until now i have been specifying one formid to look for in the join, but now i need to specify multiple ones.
If I use WHERE form_id = 1 OR form_id = 2 OR form_id = 3 ... I get a result of only the first form match that is found per company..
If I mix up the query so it looks for the forms 1st and returns multiple records for each company with different form data - that works in this sense..
But I am then looping through this array in a view and creating a table row per record (previously each row was a new company) but using the latter would cause multiple records to show for the same company.
Any way I can do this? I tried group by with the latter method but this results in only 1 record again.
SELECT DISTINCT p.project_company_has_user_id, p.project_company_has_user_project_id, p.project_company_has_user_user_id, c.company_id, c.company_hall_no, c.company_company_name, c.company_type, c.company_country, c.company_stand_number, c.company_image_file_1, p2.project_id, p2.project_name, u.user_id, u.user_username, o.orders_id, o2.order_detail_id, o2.order_detail_product_id, f2.form_question_has_answer_id, f2.form_question_has_answer_request, f2.form_question_has_answer_form_id, f2.form_question_has_answer_user_id
FROM project_company_has_user p
INNER JOIN company c ON p.project_company_has_user_company_id = c.company_id
INNER JOIN project p2 ON p.project_company_has_user_project_id = p2.project_id
INNER JOIN user u ON p.project_company_has_user_user_id = u.user_id
INNER JOIN form f ON p.project_company_has_user_project_id = f.form_project_id
LEFT JOIN orders o ON p.project_company_has_user_user_id = o.orders_user_id
LEFT JOIN order_detail o2 ON ((o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
LEFT JOIN form_question_has_answer f2 ON ((f2.form_question_has_answer_form_id = 297 AND f2.form_question_has_answer_user_id = p.project_company_has_user_user_id))
WHERE (f.form_template_name = "custom" AND p.project_company_has_user_garbage_collection = 0 AND p.project_company_has_user_project_id = 48) AND (LCASE(c.company_country) LIKE "%uk%" OR LCASE(c.company_country) LIKE "%uk%") ORDER BY company_company_name asc
you need another field in order_detail as o2 . this field is row_index(position),etc for positioning record
LEFT JOIN order_detail o2 ON (o2.row_index=1 AND (o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
Personally I would use an Outer Join for the table of which elements you need to list all matches. Should you them need to clean up that data you can build the logic into the Join Condition (as step 2). Depending on the volume of data you are handling and whether or not you need to reuse it later in the same proc, you may want to post that primary dataset into a temp table and use that as source (primary) for your later logic.
Hope that helps. If you need the code, let me know, but it is pretty straight forward.
Regards
Mac

Categories