PHP Mysql Correctly Iterate Over Tables With Alias Names - php

I have the following Mysql query:
$sql = "select r.brand AS brand, r.name AS name, r.cost AS cost, e.price AS price, d.shipping as shipping
FROM tab.rawproduct r
INNER JOIN price e ON r.housecode=e.housecode
INNER JOIN product d ON e.productid=d.productid
WHERE r.housecode='$housecode'";
The houscode is assigned to a variable which is then passed to the sql statement:
<label>Housecode:</label><input class="boxes" type="text" name="housecode" value="<?php echo $housecode; ?>"><br />
$housecode = $_POST['housecode'];
Housecode is submitted through a form with action set to $_SERVER[PHP_SELF]
I am trying to iterate over the results with PHP with the following:
$result = $con->query($sql);
if ($result->num_rows >0) {
while($row = mysqli_fetch_array($result)) {
$brand = $row['brand'];
$housecode = $row['housecode'];
$name = $row['name'];
$cost = $row['cost'];
$salesprice = $row['price'];
$shipraw = $row['shipping'];
}
} else {
echo "0 Results";
}
$con->close();
Nothing is getting returned when a user submits a housecode and the "0 Results" is echoed.
I have looked into this problem and read Lucas Knuth's post:
If two or more columns of the result have the same field names, the
last column will take precedence. To access the other column(s) of the
same name, you must use the numeric index of the column or make an
alias for the column. For aliased columns, you cannot access the
contents with the original column name. So, you can either use an AS
in your SQL-query to set other names for the doubled rows or use the
numbered indexes to access them.
So I have used the AS keyword in the above query but I still don't get any results. I have also tried changing to mysqli_fetch_row($result) and tried to assign the $row[0], 1 ... etc instead. Again no luck.
When I run Apache error_log I get the following:
Trying to get property of non-object on line 34. On line 34 and 35 I have:
if ($result->num_rows >0) {
while($row = mysqli_fetch_array($result)) {
Any help would be much appreciated.
Cheers

I have figured out the answer for myself.
The problem was that I was selecting just one database, ie tab.rawproduct BUT tables price e and procduct d are from a totally different database.
So the sql query should have been this:
$sql = "SELECT r.brand, r.name, r.cost, e.price, d.shipping FROM
tab.rawproduct r
INNER JOIN t1.price e on r.housecode=e.housecode
INNER JOIN t1.product d on e.productid=d.productid
WHERE r.housecode = '$housecode' ";
If found the error by checking the mysqli->errno:
if(!$result = $mysqli->query($sql)) {
echo "Error: Our query failed to execute and here is why: \n";
echo "Query: " . $sql . "\n";
echo "Errno: " . $mysqli->errno . "\n";
echo "Error: " . $mysqli->error . "\n";
exit;
}
Hopefully this may help someone else facing the same problem.
Thanks for all your comments and help.

I reproduced your example and I found a bug in your select query: you're missing the r.housecode.
$sql = "select r.brand AS brand, r.name AS name, r.cost AS cost, e.price AS price, d.shipping as shipping, r.housecode AS housecode
FROM tab.rawproduct r
INNER JOIN price e ON r.housecode=e.housecode
INNER JOIN product d ON e.productid=d.productid
WHERE r.housecode='$housecode'";
Check if the cross references match in your tables, because in my examples the rows are correctly returned
table price:
housecode productid price
HT0008 4 3400
HT0008 5 5400
table product:
shipping productid
64 4
78 5
table rawproduct:
brand name cost housecode
Cani bellaaa 63824 HT0008

Related

Echo contents of JOIN SQL tables with MySQLi

I'm working on a system, and this module is supposed to echo the contents of the database.
It worked perfectly until I added some JOIN statements to it.
I've checked and tested the SQL code, and it works perfectly. What's not working is that part where I echo the content of the JOINed table.
My code looks like this:
$query = "SELECT reg_students.*, courses.*
FROM reg_students
JOIN courses ON reg_students.course_id = courses.course_id
WHERE reg_students.user_id = '".$user_id."'";
$result = mysqli_query($conn, $query);
if (mysqli_fetch_array($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
echo $row["course_name"];
echo $row["course_id"];
The course_name and course_id neither echo nor give any error messages.
UPDATE: I actually need to increase the query complexity by JOINing more tables and changing the selected columns. I need to JOIN these tables:
tutors which has columns: tutor_id, t_fname, t_othernames, email, phone number
faculty which has columns: faculty_id, faculty_name, faculty_code
courses which has columns: course_id, course_code, course_name, tutor_id, faculty_id
I want to JOIN these tables to the reg_students table in my original query so that I can filter by $user_id and I want to display: course_name, t_fname, t_othernames, email, faculty_name
I can't imagine that the user_info table is of any benefit to JOIN in, so I'm removing it as a reasonable guess. I am also assuming that your desired columns are all coming from the courses table, so I am nominating the table name with the column names in the SELECT.
For reader clarity, I like to use INNER JOIN instead of JOIN. (they are the same beast)
Casting $user_id as an integer is just a best practices that I am throwing in, just in case that variable is being fed by user-supplied/untrusted input.
You count the number of rows in the result set with mysqli_num_rows().
If you only want to access the result set data using the associative keys, generate a result set with mysqli_fetch_assoc().
When writing a query with JOINs it is often helpful to declare aliases for each table. This largely reduces code bloat and reader-strain.
Untested Code:
$query = "SELECT c.course_name, t.t_fname, t.t_othernames, t.email, f.faculty_name
FROM reg_students r
INNER JOIN courses c ON r.course_id = c.course_id
INNER JOIN faculty f ON c.faculty_id = f.faculty_id
INNER JOIN tutors t ON c.tutor_id = t.tutor_id
WHERE r.user_id = " . (int)$user_id;
if (!$result = mysqli_query($conn, $query)) {
echo "Syntax Error";
} elseif (!mysqli_num_rows($result)) {
echo "No Qualifying Rows";
} else {
while ($row = mysqli_fetch_assoc($result)) {
echo "{$row["course_name"]}<br>";
echo "{$row["t_fname"]}<br>";
echo "{$row["t_othernames"]}<br>";
echo "{$row["email"]}<br>";
echo "{$row["faculty_name"]}<br><br>";
}
}

Find MIN -values but maintain row values in PHP mysqli

I have a table with 32 rows, with pairwise rows containing same "name-values", but with different raspberry-values (respectively "one" and "two".)
I want to extract each row with a unique name and the lowest average_distance - giving me 16 rows, and for that I am using this query:
SelectFinally();
function SelectFinally (){
$con = connectToDB();
$sql = "SELECT name,MIN(average_distance),raspberry From average GROUP BY name";
$result= mysqli_query($con,$sql);
$num_rows = mysqli_num_rows($result);
echo "number of rows" .$num_rows ."<br />";
while($row=mysqli_fetch_assoc($result)) {
extract($row);
$name = $row['name'];
$distance = $row['MIN(average_distance)']; //."<br />";
$raspberry = $row['raspberry']; //."<br />";
echo "select inside selectFinally name: " .$name ." distance: " .$distance ." raspberry " .$raspberry ."<br />";
}
}
This query gives me the lowest values of the average_distance allright, BUT it messes up my raspberry values. e.g. blÄ_bil should have a raspberry value of "two", hence it has the lowest average_distance - value.
I can not seem to get it right. Would somebody please help me to get it right?
try:
SELECT a.name, a.raspberry
FROM average a
INNER JOIN
(
SELECT name, MIN(average_distance) as avg_dist
FROM average
GROUP BY name
) a2 ON a.name = a2.name AND a.average_distance = a2.avg_dist
Instead of SELECT name,MIN(average_distance),raspberry From average GROUP BY name
thanks Nishant Matha
It worked - I simply needed to add te raspberry in my first select. Now it adds the average_distance to the output.
$sql = "SELECT a.name, a.average_distance, a.raspberry
from average a
INNER JOIN
(
select name,MIN(average_distance) AS avg_dist,raspberry
FROM average
GROUP BY name
)
a2 ON a.name=a2.name AND a.average_distance = a2.avg_dist ";

Join columns from two mysql tables

I'm trying to figure out the following. In the beginning I want to check if a member is in groups 11, 43 or 1.
I have the following tables with columns:
table members (member_id, name, group)
334 Ronald 43
table content (member_id, value)
334 Gold
I'm looking for a query which displays the name FROM members and value FROM content, joined with member_id and end result something like
Ronald Gold
If the user is not in the groups I have set, he/she will not be displayed.
The following is what i have managed to do
$sql = 'SELECT * FROM members m INNER JOIN content p ON m.member_id = p.member_id ';
$retval = mysql_query( $sql, $conn );
and
while($row = mysql_fetch_array($retval, MYSQL_ASSOC)) {
echo $row['member_id']. " " .$row['value'];
echo "<br>";
}
will output 334 Gold.
I just need to check the group in the beginning and replace member_id with name in the final output. Any help?
Just adjust your mysql query:
$sql = 'SELECT m.name, p.value FROM members m JOIN content p ON m.member_id = p.member_id WHERE m.group = 1 OR m.group = 11 OR m.group = 43;
then
echo $row['name']. " " .$row['value'];
Also you should be using mysqli_query() or PDO::query() since mysql_query() is deprecated. Reference
When you're echoing the results if you change echo $row['member_id'] to echo $row['name'] you will get the member's name.
Returning $row['group'] will tell you which group the member is in.
Your SQL should return following construct for each row
(member_id, name, group, value)
to filter out members not in desired groups modify your query
$sql = 'SELECT * FROM members m INNER JOIN content p ON m.member_id = p.member_id WHERE m.group IN (11,43,1) ';
Side note:
Consider using PDO or mysqli_* instead of mysql_* as mysql_* is deprecated and gone in PHP7

PDO multiple select queries

I am trying to get rows out of 2 tables. The first query works. But the second doesn't. This is my code:
echo '<table width="100%">';
echo '<tr><td>Product</td><td>Quantity</td><td>Price</td><td>Remove</td></tr>';
foreach ($_SESSION['cart'] as $key => $cartproduct) {
list($productid, $productquantity) = split("\|", $cartproduct, 2);
global $db;
$result = $db->prepare('SELECT name FROM products WHERE ID= :ID LIMIT 1; SELECT price FROM prices WHERE productid = :ID AND quantity = :quantity LIMIT 1');
$result->bindParam(':ID', $productid);
$result->bindParam(':quantity', $productquantity);
$result->execute();
$row = $result->fetch();
if($result->RowCount() == 1){
echo '<tr><td>' . $row['name'] . '</td><td>' . $productquantity . '</td><td>' . $row['price'] . '</td><td>Remove</td></tr>'; //LINE15
}else{
unset($_SESSION['cart'][$key]);
}
}
echo '</table>';
The row name is from the products table and the name price is from the prices table. This is the error I get:
Notice: Undefined index: price in /var/www/html/design2/pages/cart.php on line 15
I am sure the query is working. Can anyone tell my what i am doing wrong?
You are receiving index not defined because of the way your query is structured. You have:
SELECT name FROM products WHERE ID= :ID LIMIT 1; SELECT price FROM prices WHERE productid = :ID AND quantity = :quantity LIMIT 1
This is structured to return 2 result sets. You grab the first result set here:
$row = $result->fetch();
But then you try to access $row['price'] which doesn't exist in that result set. That result set is only the result from the first SELECT. You can see this if you just var_dump($row) and see what your result set looks like.
It looks like you can combine your query so that you get one result set:
SELECT p.name, pp.price FROM products p
INNER JOIN prices pp ON p.ID = pp.productid
WHERE p.ID= :ID AND pp.quantity = :quantity
LIMIT 1;
If you can't combine the queries into one, then you should iterate over your result sets and access the relevant $row index. That would look something like:
while($row = $result->fetch()) {
if(isset($row['name'])) {
//do something
} else if(isset($row['price'])) {
//do something else
}
}
Some things to consider:
You may need a LEFT JOIN instead of an INNER JOIN. This depends on
whether or not products always have a corresponding record in the
prices table.
I'm not sure what you're trying to achieve with
LIMIT 1. You may need to consider and ORDER BY -- unless it really
doesn't matter which record you return in your result.
You should consider testing your variables $productid and $productquantity to verify they have your intended values after splitting $cartproduct. What if one is empty / blank ?
You should test your result before trying to access the result array at a specific index.
For example:
if(isset($row['name']) && isset($row['price'])) {
//echo your results
} else {
//return an error
}

Display Multiple PHP Queries

I need to display multiple queries (they can't be combined into one large query, at least I don't think so) together in a webpage. I'll explain a little about the queries to give an idea of the problem. I have a database in MySQL with 3 question tables of the same format linked to a response table via a classid. The response table is linked to an instructor table via an instructorid. I need to display a table showing all 3 question scores for each record existing for an instructor, with each table followed by some text indicating which question had the highest value as well as the least. I created a uniontbl view in MySQL which is a union query with fields ClassID, Average and TableName. What I have so far is:
$query2 = "SELECT `tbl_instructor`.`FirstName`,
`tbl_instructor`.`LastName`,
`tbl_term`.`TermID`,
`tbl_ucourse`.`Abbreviation`,
`tbl_ucourse`.`Series`,
`tbl_uquestion01`.`Average` AS `Q1`,
`tbl_uquestion02`.`Average` AS `Q2`,
`tbl_uquestion03`.`Average` AS `Q3`
FROM `tbl_instructor`
LEFT JOIN `undergrad`.`tbl_uresponse` ON `tbl_instructor`.`InstructorID` = `tbl_uresponse`.`InstructorID`
LEFT JOIN `undergrad`.`tbl_ucourse` ON `tbl_uresponse`.`CourseID` = `tbl_ucourse`.`CourseID`
LEFT JOIN `undergrad`.`tbl_Term` ON `tbl_UResponse`.`TermID` = `tbl_Term`.`TermID`
LEFT JOIN `undergrad`.`tbl_uquestion01` ON `tbl_uresponse`.`ClassID` = `tbl_uquestion01`.`ClassID`
LEFT JOIN `undergrad`.`tbl_uquestion02` ON `tbl_uresponse`.`ClassID` = `tbl_uquestion02`.`ClassID`
LEFT JOIN `undergrad`.`tbl_uquestion03` ON `tbl_uresponse`.`ClassID` = `tbl_uquestion03`.`ClassID`
WHERE CONCAT(LastName, ', ', FirstName, ' (', UserID, ')') = '{$instructor}'";
$query3 = "SELECT `tbl_instructor`.`FirstName`,
`tbl_instructor`.`LastName`,
`uniontbl`.`ClassID`,
`uniontbl`.`TableName`,
`tbl_uresponse`.`InstructorID`
FROM `tbl_Instructor`
LEFT JOIN `undergrad`.`tbl_uresponse` ON `tbl_instructor`.`InstructorID` = `tbl_uresponse`.`InstructorID`
LEFT JOIN `undergrad`.`uniontbl` ON `tbl_uresponse`.`ClassID` = `uniontbl`.`ClassID`
WHERE CONCAT(LastName, ', ', FirstName, ' (', UserID, ')') = '{$instructor}'
ORDER BY `uniontbl`.`Average` DESC
LIMIT 1";
$query4 = "SELECT `tbl_instructor`.`FirstName`,
`tbl_instructor`.`LastName`,
`uniontbl`.`ClassID`,
`uniontbl`.`TableName`,
`tbl_uresponse`.`InstructorID`
FROM `tbl_Instructor`
LEFT JOIN `undergrad`.`tbl_uresponse` ON `tbl_instructor`.`InstructorID` = `tbl_uresponse`.`InstructorID`
LEFT JOIN `undergrad`.`uniontbl` ON `tbl_uresponse`.`ClassID` = `uniontbl`.`ClassID`
WHERE CONCAT(LastName, ', ', FirstName, ' (', UserID, ')') = '{$instructor}'
ORDER BY `uniontbl`.`Average` ASC
LIMIT 1";
$result2 = mysqli_query($query2);
$result3 = mysqli_query($query3);
$result4 = mysqli_query($query4);
while($row2 = mysqli_fetch_assoc($result2))
{
echo "<br>";
echo"<table>";
echo "<tr>";
echo "<th>Q1</th>";
echo "<th>Q2</th>";
echo "<th>Q3</th>";
echo "</tr>";
echo "<tr>";
echo "<td>" . $row2['Q1'] . "</td>";
echo "<td>" . $row2['Q2'] . "</td>";
echo "<td>" . $row2['Q3'] . "</td>";
echo "</tr>";
echo"<br>";
echo "</table>";
while($row3 = mysqli_fetch_assoc($result3))
{
echo $row3['TableName'];
}
echo "<br>";
while($row4 = mysqli_fetch_assoc($result4))
{
echo $row4['TableName'];
}
echo "<br>";
}
So, how I've tried to tackle the problem is using the second and third queries to determine which questions had the highest and lowest score from the uniontbl view and displaying that after each table containing the question scores. The problem is that the second and third queries ONLY display after the first table (or record) and do not show at all after that. I have a feeling that the problem lies in the actual queries themselves but I can't think of another way to solve the problem. P.S. I know my code isn't the best (echoing HTML and such) but I'm just trying to get it to work...
After you print the first row of $result2, you fetch all the rows of $result3 and $result4. So after you print the second row of $result2, there's nothing left to fetch from the second and third queries.
Since the second and third queries use LIMIT 1, there's just one row for each of them. You could fetch them each once, and then display that row after each row of the first query. But I'm not sure why you need to display the same thing multiple times. Maybe you should just show the output of these two queries once, at the beginning or end, rather than after each row.
Also, do you really want to create a whole new table for each row of $result2? Usually each row is just a row in one big table, not a separate table with just one row for each row from the DB.

Categories