Multiple Inner Joins and one to one // one to many relationship - php

I have this query below.. All of the relationships of the tables are one to one relationships except for ASSOCPRODUCTS table where there are two products per order. Everything seems to work fine, except for that my query returns only one row, and thus, will only return ONE product id when there are in fact two. I understand why it's only pulling one, in that there is only ONE order per orderID, but there are two Associated Products for each contract and I need to get each product id. in the Assocproducts table, each product gets its own row, as it is a one to many wit the contracts table.
Is it possible to get that information using inner joins, or do I need to run another query?
$orderid = $_POST['orderid'];
$res = mysql_query ("
SELECT company.name as cname,
orders.datemade as datemade
orders.p1quantity as p1q,
orders.p2quantity as p2q,
assocproducts.productid as pid,
assocproducts.price as pprice,
inventory.name as pname,
inventory.quantity as pquantity
FROM orders
INNER JOIN contracts ON (contracts.id = orders.contractid)
INNER JOIN company ON (contracts.companyid = company.id)
INNER JOIN assocproducts ON (contracts.id = assocproducts.contractid)
INNER JOIN inventory ON (assocproducts.productid = inventory.id)
WHERE orders.id = " . $orderid);
$order = mysql_fetch_assoc($res);
Please let me know if I need to give more information.
$order isn't in a loop, because I need to display ONLY the order info for this specific order. It's an AJAX trigger on click.
Thanks!

I think you're wrong stating that only one row is returned. I created a fresh schema with only the columns used in your query, populated it with sample data and got out all matching results. I think the problem is with your usage of mysql_fetch_assoc() function. Semantics of this function are clear:
Returns an associative array of strings that corresponds to the fetched row, or FALSE if there are no more rows.
so my guess is you never call mysql_fetch_assoc() again.
Given semantics of INNER JOIN and your data constraints, your query will always produce 0 or 1 rows. If you don't know why - please read SQL JOIN types & behavior. So, you have two options to fetch order details and information about associated products:
Use two separate select statements - one for order details (always 1 row), second for associated products (2 rows). Iterate on results of the second query - you will get information about one product for each row fetched.
Keep your existing query, but change the way you retrieve data from it by iterating over all rows (note that order information will be present in all fetched rows and will be the same for all of them):
$firstRow = true;
while (($order_product = mysql_fetch_assoc($res)) !== FALSE) {
if ($firstRow) {
// do something with order info
// but don't repeat it for consecutive rows
$firstRow = false;
}
// do something with currently fetched associated product info
}
It's a matter of taste, but I'd go with the first option - it looks less hacky.

Related

How to select from mysqli if value from other table equals specific value?

I know I should post a code of what I've tried so far. I really don't know where to start. So at this moment I have 2 working mysqli statements, but I don't know how to combine them.
So, I have two tables.
$sql_ONE = mysqli_query($mysqli, "SELECT * FROM todo WHERE status='open' ORDER BY date ASC LIMIT " . $offset . "," . $items_per_page);
$sql_TWO = mysqli_query($mysqli, "SELECT * FROM permission WHERE memberID=$memberID AND allowed='yes'");
I use $offset and $items_per_page for pagination.
But here it comes: there's a second table that contains a list of members, their memberID and a value (yes/no) wether they may see the row from the first statement or not. So in the first mysqli-statement, all rows are selected where status=open. Before this row's printed on the screen, PHP needs to check if the member who is on the page is allowed to see it. So it should only be shown if allowed=yes.
I don't want them to be in one table, because then I need a row for every single member.
How can I combine those two tables and show them on my screen, still with pagination showing the right amount of rows?
I dont know exactly about your database but by so far understanding I have derived this
SELECT todo.ID
FROM todo
LEFT JOIN permission
ON todo.ID=permission.ID
where permission.allowed='Yes' AND permission.memberID=$memberID
It will join two tables 'todo' and 'perrmission' and will return ID of 'todo' on the basis of condition from permission table.

Relate 2 tables in database

I have 2 tables in a database. One is for product data, and the other is for the images of the products. I have to set up an slider in the index of my page, and there will go specific images (like products with 50% discount, or sth like that). I'll make a query to my product table in my database, to get the id of the product that are on sale
$query1="SELECT id FROM products WHERE price<'100'";
$query2=mysql_query($query1);
$idSales=mysql_fetch_array($query2);
So, now i have an array with the id's of the products that I'm interested in, and here comes the trouble. How can I deal with that array that mysql_fetch_array returned to me? How can I make the query to the images table (
in that table I have the id of the corresponding product, so I've to match one with the other)
You can join these two tables to get images of the products.
Run this query
SELECT i.`imageName`
FROM products p INNER JOIN images i
ON p.`id`=i.`idProduct`
WHERE p.price<100
You can try running multiple inline queries.For performance considerations I would not suggest doing this but it can get the job done with less number of records:
while($row = mysql_fetch_array($query2)){
$id = $row['id'];
//now create a new query
$img_query = "SELECT * FROM ... where id=".$id;
//run query and process results
$img_result = mysql_fetch_array($img_query)
//work with image related results here
}
You can also create a sql array and run the query after the while loop is finished.
Or you can use subrequest
SELECT * FROM images WHERE product_id IN (SELECT id FROM products WHERE price < '100')

MySQL Join table and get results that don't exist in one

I have two tables, one that has a foreign key from the other. I want to get all records that don't exist in the foreign table, based on certain criteria.
Here are the tables I have:
item_setting
setting_id
category_id
item
item_id
setting_id
name
expired_dt
Here's the query I'm using now:
SELECT
iset.setting_id
FROM
item_settings iset
LEFT OUTER JOIN
item i ON i.setting_id = iset.setting_id
WHERE
iset.category_id = '5' AND i.setting_id is null
This query works in providing any setting_id's that do not have a record in the item's table within a specific category.
However, now I want to include cases where the expired_dt less than than time() (meaning it's past expired). In otherwords, I would think to add this:
WHERE
iset.category_id = '5' AND (i.setting_id is null OR i.expired_dt < '".time()."')
However, this doesn't work, it returns all the records.
Any suggestions? Maybe I'm completely over complicating this.... I just want to return the setting_id's from the item_settings table, where the expired_dt associated in the item table is expired or if it does not even exist in the item table.
Thank you!
Try moving the timestamp condition into the join clause. Something like
item_settings iset
LEFT OUTER JOIN
item i ON i.setting_id = iset.setting_id and i.expired_dt > time()

How to create MYSQL record source for two related tables

I currently have a page that displays player information from one table named "tblplayers". The query I am currently using is:
$result = mysql_query("SELECT * FROM tblPlayers WHERE lng_RecordID_PK = '".$playerid."' ");
I have a second table named "tblMatches" containing match results for the players. I want the recordset to include the rows from "tblMatches" WHERE "P1_ID" OR "P2_ID" is equal to the "lng_RecordID_PK" field from "tblPlayers".
How can I revise my $result query so that it returns:
one row from tblPlayers
multiple rows from tblMatches
???
Thanks for helping me out.
That's called a 'join':
SELECT tblPlayers.*, tblMatches.*
FROM tblPlayers
LEFT JOIN tblMatches ON Ing_RecordID_PK IN (P1_ID, P2_ID)
You are asking about joining two tables where the second table potentially has multiple records for each one in the first table. This is a one-to-many or 1:N join, and most often done using a LEFT JOIN meaning you want everything in the "left" table, and all the records that match from the "right" table, and that you may have some records on the "left" side with no matches.
Your query would look like this:
SELECT *
FROM tblPlayers
LEFT JOIN tblMatches
ON (tblPlayers.lng_RecordID_PK = tblMatches.P1_ID
OR tblPlayers.lng_RecordID_PK = tblMatches.P2_ID)
WHERE tblPlayers.lng_RecordID_PK = #PlayerID;
Bits of advice:
Avoid selecting all columns (*) and instead select just those that you need for the query.
Consider using parameterized queries to avoid SQL injection attacks. If your variable were to be submitted or altered maliciously, it could result in compromised data or security. (See PHP Data Objects for example.)
There is no way to get rows from two different tables in the way you are describing. You could not get a row from one table, and two rows from another one. What you could is do two separate queries, or use a JOIN statement to join the two tables together, and then receive results from the resulting joined table. If you provide more information about your table structure I am sure more help can be given.

PHP MYSQL Query Multiple Tables Where the Second Table returns multiple rows

I'm trying to query 2 tables where the first table will return 1 row and the second table will return multiple rows. So basically the first table with return text on a page and the second table will return a list that will go within the page. Both tables have a reference row which is what both tables are queried on. (See Below)
SELECT shop_rigs.*, shop_rigs_images.*, shop_rigs_parts.*
FROM shop_rigs
LEFT JOIN shop_rigs_images
ON shop_rigs.shoprigs_ref = shop_rigs_images.shoprigsimg_ref
LEFT JOIN shop_rigs_parts
ON shop_rigs.shoprigs_ref = shop_rigs_parts.shoprigsparts_ref
WHERE shoprigs_enabled='1' AND shoprigs_ref='$rig_select'
ORDER BY shoprigs_order ASC
Is it better to just do 2 queries?
Thanks,
dane
I would do this in two queries. The problem isn't efficiency or the size of the respective tables, the problem is that you're create a Cartesian product between shop_rigs_images and shop_rigs_parts.
Meaning that if a given row of shop_rigs has three images and four parts, you'll get back 3x4 = 12 rows for that single shop_rig.
So here's how I'd write it:
SELECT ...
FROM shop_rigs
INNER JOIN shop_rigs_images
ON shop_rigs.shoprigs_ref = shop_rigs_images.shoprigsimg_ref
WHERE shoprigs_enabled='1' AND shoprigs_ref='$rig_select'
ORDER BY shoprigs_order ASC
SELECT ...
FROM shop_rigs
INNER JOIN shop_rigs_parts
ON shop_rigs.shoprigs_ref = shop_rigs_parts.shoprigsparts_ref
WHERE shoprigs_enabled='1' AND shoprigs_ref='$rig_select'
ORDER BY shoprigs_order ASC
I left the select-list of columns out, because I agree with #Doug Kress that you should select only the columns you need from a given query, not all columns with *.
If you're pulling a large amount of data from the first table, then it would be better to do two queries.
Also, for efficiency, it would be better to specify each column that you actually need, instead of all columns - that way, less data will be fetched and retrieved.
Joins are usually more efficient than running 2 queries, as long as you are joining on indexes, but then it depends on your data and indexes.
You may want to run a "explain SELECT ....." for both options and compare "possible keys" and "rows" from your results.

Categories