I'm dealing with a junction table for a many to many relationship between products and categories. With this particular function I'm attempting to take in a product_ID variable and get all associated category names in an array. However, with the current setup I'm only getting one category per product ID when I know several have 2. Any thoughts? Also anyone know of a good simple solution to more visually keeping track of M2M relationships in mysql?
//INPUT PRODUCT ID, GET ASSOCIATED CATEGORIES
function productcat($pid) {
global $sql;
$query = "SELECT * FROM Product_Category WHERE Product_ID = '$pid'";
$result = mysqli_query($sql, $query);
$catidarray = array();
while($row = mysqli_fetch_array($result)) {
array_push($catidarray, $row['Category_ID']);
}
foreach($catidarray as $i) {
$query = "SELECT * FROM Categories WHERE Category_ID = '$i'";
$result = mysqli_query($sql, $query);
$namearray = array();
while($row = mysqli_fetch_array($result)) {
array_push($namearray, $row['Name']);
}
}
return $namearray;
}
There is something wrong with your function.
In your second foreach, you put the variable $namearray inside the loop which on every run resets its value to empty array $namearray = array();. Just put that outside the foreach:
//--> put it here
$namearray = array();
foreach($catidarray as $i) {
$query = "SELECT * FROM Categories WHERE Category_ID = '$i'";
$result = mysqli_query($sql, $query);
while($row = mysqli_fetch_array($result)) {
array_push($namearray, $row['Name']);
}
}
And, I just want to make some suggestions on your function. Since you have the junction table, you don't really need to have a separate query for product and category in order to get your desired values from those tables.
Just do the INNER JOIN to maximize the use of your table relations.
Use your junction table Product_Category because that's the real purpose why created that.
SELECT *
FROM Product_Category AS a
INNER JOIN Category AS b
ON a.Category_ID = b.Category_ID
WHERE Product_ID = $pid
In your function, you may try this: havent tested but hope this will give you idea.
//INPUT PRODUCT ID, GET ASSOCIATED CATEGORIES
function productcat($pid) {
global $sql;
$query = "SELECT *
FROM Product_Category as a
INNER JOIN Category as b
ON a.Category_ID = b.Category_ID
WHERE Product_ID = {$pid}";
$result = mysqli_query($sql, $query);
$namearray = array();
while($row = mysqli_fetch_array($result)) {
array_push($catidarray, $row['Name']);
}
return $namearray;
}
Then that's it :)
And by the way, in the latest version of php, mysql_ functions are already deprecated. Much better if you will be going to use PDO or MySQLi.
Check this also: PDO vs. MySQLi
Related
I have one table with categories and another table with linkrecords for each category and the table structure looks like this:
categories:
id (int)
name (varchar)
links:
id (int)
link (varchar)
fk_cat_id (int)
Here is how I do now, but know that it is a no go with a query within a query:
$query = "SELECT * FROM categories";
if ($result = $mysqli->query($query)) {
while ($row = $result->fetch_assoc()) {
$catid = $row['cat_id'];
echo 'CatName: '.$row['name'];
echo '<ul>';
$query2 = "SELECT * FROM links WHERE fk_cat_id = $catid";
if ($result2 = $mysqli->query($query2)) {
while ($row2 = $result2->fetch_assoc()) {
echo '<li>'.$row2['link'].'</li>';
}
}
echo '</ul>';
}
}
I guess I have to go to some JOIN method, but not sure how!
Following query will be used to retrieve links with relation to link categories.
Also, It is a good practice to specify fields name in query to retrieve specific columns only instead of *.
SELECT links.id AS link_id, links.link, links.fk_cat_id, categories.name
FROM links
JOIN categories ON categories.id = links.fk_cat_id;
I have the following code:
// db connection info set up earlier
$sql= "SELECT `TABLE_1.ID`, `TABLE_2.ID`, `POTATO` FROM `TABLE_1.ID` LEFT JOIN `TABLE_2` ON `TABLE_1`.`ID` = `TABLE_2`.`ID_OF_OTHER_TABLE`;";
$rows = mysqli_query($connection, $sql);
foreach ($rows as $row){
$potato = $row["POTATO"];
$id = $row["TABLE_2.ID"];
}
I can't get TABLE_2.ID. I've tried to doing a print_r to get the proper format, but it says it's a mysqli object and I don't get much more info than that. However, I can get potato. So I'm guessing it's a calling syntax issue, but I've searched multiple sites (stack and google included) and not found a clear answer. So, what do I need to do instead of
$id = $row["TABLE_2.ID"];
?
Assign aliases to the columns with the same name.
$sql= "SELECT `TABLE_1`.`ID` AS t1_id, `TABLE_2`.`ID` AS t2_id, `POTATO`
FROM `TABLE_1.ID`
LEFT JOIN `TABLE_2` ON `TABLE_2`.`ID_OF_OTHER_TABLE` = `TABLE_1`.`ID`;";
$rows = mysqli_query($connection, $sql);
foreach ($rows as $row){
$potato = $row["POTATO"];
$id = $row["t2_id"];
}
You can't left join a table with itself, you also cannot have a table that isn't joined = something from another table that cannot be joined to itself.
This will work:
// db connection info set up earlier
$sql= "SELECT TABLE_1.ID, TABLE_2.ID, POTATO
FROM
TABLE_1.ID
LEFT JOIN TABLE_2 ON TABLE_1.ID = TABLE_2.ID";
$rows = mysqli_query($connection, $sql);
while ($row = mysqli_fetch_assoc($rows)) {
echo ($row['ID']);
}
mysql_free_result($rows);
I have a small issue that I can't figure out.
I have to pull data from two different tables, in one loop. I've never done that before, so I have no idea how. I tried two different queries. That looked like this:
$query = "SELECT * FROM colors ";
$color_select = mysqli_query($connection, $query);
$second_query = "SELECT * FROM votes";
$vote_select = mysqli_query($connection, $second_query);
And then put them into a loop:
while($row = mysqli_fetch_assoc($color_select) && $second_row = mysqli_fetch_assoc($vote_select))
{
$color = $row['Colors'];
$votes = $second_row['Votes'];
echo "<tr><td>$color</td><td>$votes</td></tr>";
}
But that didn't work. I didn't expect it to, just wanted to try. :) Maybe someone experienced can help me out. Thanks.
At the end of the day I need a table displayed, that has two columns, one of them contains the color name from one DB table and the other one contains a number of votes.
As requested: table structures.
Table: colors has only one field Colors.
Table: votes has four fields city_id, City, Colors and Votes
*************************EDIT**************************************
So fixed up the query as suggested, but is still shows nothing.
Here is the edited code:
$query = "SELECT * FROM colors,votes WHERE colors.Colors=votes.Colors";
$color_votes_select = mysqli_query($connection, $query);
while($row = mysqli_fetch_assoc($color_votes_select))
{ $color = $row['Colors'];
$votes = $row['Votes']; }
if table having relation.
try this in single query .
SELECT
`colors`.*,votes.*
FROM
`colors`
INNER JOIN
`votes` ON
`votes`.colorId = `colors`.Id
Most imp *****You should have some relationship between tables
Otherwise workaround
Run query on color, Save it in ArrayA
Run query on vote, Save it in ArrayB
Create New Array ArrayC
$arrayC = array();
Loop array A or C if they both contact same row count
array_push($ArrayC, key and value of color, key and value of votes);
Final loop ArrayC to print tr and td
First Relate These two tables, write color_id in votes table.
$query = "SELECT * FROM colors,votes where colors.id=votes.color_id";
$color_select = mysqli_query($connection, $query);
while($row = mysqli_fetch_assoc($color_select))
{
$color = $row['Colors'];
$votes = $row['Votes'];
}
Try this:
$query = "SELECT colors FROM colors";
$color_select = mysqli_query($connection, $query) or die (mysqli_error());
$second_query = "SELECT votes FROM votes"; //you only need column votes right?
$vote_select = mysqli_query($connection, $second_query) or die (mysqli_error());;
while( $row = mysqli_fetch_assoc($color_select) && $second_row = mysqli_fetch_assoc($vote_select)){
$color[] = $row['colors'];
$votes[] = $second_row['votes'];
echo "<tr><td>$color</td><td>$votes</td></tr>";
}
Short explanation:
It will fetch the select and store into an array (because what you were doing is selecting multiple rows into one single variable) and then just display with the echo.
I have 2 tables in my DB, Polyptychs and Illustrations. The PK of Polyptychs is FK in Illustrations.
What I want to do is:
SELECT polyptychID FROM Polyptychs
and subsequently, foreach ID returned I need all illustrations.
Via PHP the solution is something like this(using PDO sintax):
<?php
//create the connection with DB
$sql = "SELECT polyptychID, polyptych_image FROM Polyptychs";
$stmt = $this->DBH->query($sql);
$resultTmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
$final_result = array();
foreach($resultTmp as $val){
$id = $val['polyptychID'];
$final_result["$id"]["image"] = $val['polyptych_image'];
$sql2 = "SELECT * FROM Illustrations WHERE polyptychID = :polyID";
$stmt2 = $this->DBH->prepare($sql2);
$stmt2->execute(array('polyID' => $id));
$resultTmp2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$final_result["$id"]["illustrations"] = $resultTmp2;
unset($id);
unset($sql2);
unset($stmt2);
unset($resultTmp2);
}
?>
Now $final_result contains all polyptychID as key of the array and its relative image and illustrations (if there's no error in the code).
What I want to know is if there is an easier way to get it, maybe doing it via SQL, and what is the best solution.
Thanks
You could run just one query using Inner Join:
SELECT P.polyptychID, polyptych_image, I.*
FROM Polyptychs P
INNER JOIN Illustrations I ON I.polyptychID = p.polyptychID
Now you loop the results adding them to the same array structure polyptychID as keys and illustrations as an array:
<?php
$sql = "SELECT P.polyptychID, polyptych_image, I.*
FROM Polyptychs P
INNER JOIN Illustrations I ON I.polyptychID = p.polyptychID";
$stmt = $this->DBH->query($sql);
$resultTmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
$final_result = array();
foreach($resultTmp as $val){
$id = $val['polyptychID'];
$final_result["$id"]["image"] = $val['polyptych_image'];
// I'm not sure what's the ID for Illustration table, so I'll assume `illustrationID`
$final_result["$id"]["illustrations"][$val["illustrationID"]] = $val;
unset($id);
}
?>
Here's what I'd do, if I were you:
SELECT p.polyptychID as ID,
p.polyptych_image as image,
i.*
FROM Polyptychs p
INNER JOIN Illustrations i
ON i.polyptychID = p.polyptychID
In light of your comment, check this handy graph to understand why an INNER JOIN is what I chose to use here:
Then, to format the array in the way you want it, just write this:
$formatted = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$id = $row['ID'];
if (!isset($formatted[$id]))
{
$formatted[$id] = array(
'image' => $row['image'],
'illustrations' => array() //we'll set this in a minute
);
}
unset($row['ID'], $row['image']);//remove id & image values
$formatted[$id]['illustrations'][$row['illustrationsID']] = $row;//assign rest of result-set
}
Of course, if there are fields in the Illustrations called either ID or image, then you'd have to change the query to p.polyptychID AS p_ID or something. Just make sure the aliasses are unique and you'll be fine.
On the re-use of prepared statements, it seems to be something people tend to overlook, but you really can use the same prepared statements over and over. As luck would have it, in fact, I wrote an answer about this matter just this morning. I use some basic examples that might be applicable to your case, too. So if -for some reason- you can't do a join, you can simply write:
$stmt = $pdo->prepare(
'SELECT * FROM Illustrations WHERE polyptychID = :pId'
);
$baseStmt = $pdo->query(
'SELECT polyptychID, polyptych_image FROM Polyptychs'
);
$result = array()
while($row = $baseStmt->fetch(PDO::FETCH_ASSOC))
{
$result[$row['polyptychID']] = array(
'image' => $row['polyptych_image'],
'illustrations' => null
);
$stmt->execute( array(':pId' => $row['pId']));
$result[$row['polyptychID']]['illustrations'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
I'm working in PHP and MySQL to create and list a membership directory. I have three tables - company, contact and branch. Companies have Contact people, and some but not all companies have Branches, which also have Contact people. I am using LEFT JOIN in my first query to connect the contact people to their respective company, and loading the results into an array, which works using the following code:
// Retrieve all the data from the "company" table
$query = "SELECT * FROM company LEFT JOIN contact ON company.company_id = contact.company_id WHERE comp_county = 'BERNALILLO' ORDER BY company.comp_name, contact.cont_rank";
$result = mysql_query($query)
or die(mysql_error());
// Build the $company_array
$company_array = array();
while($row = mysql_fetch_assoc($result)) {
$company_array[] = $row;
}
Now I am trying to figure out how to run a second query, which needs to select from my branch table all branches whose company_id match the company_id stored in my above array: $company_array. I then want to store the results of the second query into a second array called $branch_array. I have tried this:
// Retrieve all the matching data from the "branch" table
foreach($company_array as $row) {
$query2 = "SELECT * FROM branch LEFT JOIN contact ON branch.branch_id = contact.branch_id WHERE branch.company_id = '".$row['company_id']."' ORDER BY branch.br_name, contact.cont_rank";
$result2 = mysql_query($query2)
or die(mysql_error());
}
// Build the $branch_array
$branch_array = array();
while($row2 = mysql_fetch_assoc($result2)) {
$branch_array[] = $row2;
}
But this does not seem to work... Can anyone give me an example of how to do this? The query needs to run so that it checks each different company_id in my $company_array for a match in the branch table - hopefully the question makes sense. Thanks.
i think your while should be inside your foreach statement so that your $branch_array can be filled with results of all company_id values, not only the last one :
foreach($company_array as $row) {
$query2 = "SELECT * FROM branch LEFT JOIN contact ON branch.branch_id = contact.branch_id WHERE branch.company_id = '".$row['company_id']."' ORDER BY branch.br_name, contact.cont_rank";
$result2 = mysql_query($query2)
or die(mysql_error());
// Build the $branch_array
$branch_array = array();
while($row2 = mysql_fetch_assoc($result2)) {
$branch_array[] = $row2;
}
}