Mysql_stmt::bind_result() [duplicate] - php

This question already has answers here:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
(2 answers)
Closed 1 year ago.
I have the following mysql query which am executing in my php script:
$qr = "Select p.productID,p.productDesc,p.productQty,";
$qr .= "p.productPr,p.type,p.gender,p.date From";
$qr .= " products AS p";
$qr .= " INNER JOIN(Select c.productID, GROUP_CONCAT(";
$qr .= "DISTINCT c.availCol) AS color_list FROM";
$qr .= " availColors AS c GROUP BY c.productID) AS colors";
$qr .= " ON p.productID = colors.productID":
$qr .= " INNER JOIN(SELECT s.productID, GROUP_CONCAT";
$qr .= "(s.availSizes) AS size_list FROM availSizes AS s";
$qr .= " GROUP BY s.productID) AS sizes ON p.productID";
$qr .= " = sizes.productID";
$qr .= " INNER JOIN(SELECT avp.productID, avp.productImg";
$qr .= " FROM availImg AS avp ORDER BY avp.productID";
$qr .= " LIMIT 3) AS images ON images.productID = ";
$qr .= " p.productID";
$qr .= " WHERE p.productID = ?";
$qr .= " GROUP BY p.productID";
$stm = $mysqli->prepare($qr);
$stm->bind_param('s',$id);
$stm->execute();
$stm->store_result();
If($stm->num_rows == 1){
$stm->bind_result($pid,$desc,$qty,$pr,$type,$gender,
$date,$colID,$color,$sizeID,$sizes,$imgID,$imgUrl);
$stm->fetch();
......
}
When I execute the script I get an error saying:
Mysqli_stmt::bind_result(): Number of bind variables doesn't
Match number of fields in the prepared statement in...
I understand what this error means, but I have rechecked and recounted the number of bind variables in the bind_result() against the number of SELECTed columns, I just can't figure out what is wrong. I don't know how PHP evaluates values returned from a mysql subquery. Can anyone offer help on this? I have been on this all day! Thanks for any help!

$qr = "
Select
p.productID,
p.productDesc,
p.productQty,
p.productPr,
p.type,
p.gender,
p.date
From
products AS p
INNER JOIN(
Select
c.productID,
GROUP_CONCAT(DISTINCT c.availCol) AS color_list
FROM
availColors AS c GROUP BY c.productID) AS colors
ON
p.productID = colors.productID
INNER JOIN(
SELECT
s.productID,
GROUP_CONCAT(s.availSizes) AS size_list
FROM
availSizes AS s
GROUP BY
s.productID
) AS sizes
ON
p.productID = sizes.productID
INNER JOIN(
SELECT
avp.productID,
avp.productImg
FROM
availImg AS avp
ORDER BY
avp.productID
LIMIT
3) AS images
ON
images.productID = p.productID
WHERE
p.productID = ?
GROUP BY
p.productID";
Try formatting your query like this muti-line strings are perfectly fine in PHP, and it's almost impossible to make sense of it concatenated line by line. If I have it right you are missing at least a closing parentheses in there, the first inner join open parentheses is not closed.

You are only joining your other tables/columns not selecting the columns. Try adding the columns to the beginning of the query (before the FROM)
$qr = "SELECT p.productID,p.productDesc,p.productQty,";
$qr .= "p.productPr,p.type,p.gender,p.date,";
// colors columns
$qr .= "colors.productID, colors.color_list,";
// sizes columns
$qr .= "sizes.productID, sizes.size_list,";
// images columns
$qr .= "images.productID, images.productImg ";
$qr .= "From products AS p";
$qr .= " INNER JOIN(Select c.productID, GROUP_CONCAT(";
$qr .= "DISTINCT c.availCol) AS color_list FROM";
$qr .= " availColors AS c GROUP BY c.productID) AS colors";
$qr .= " ON p.productID = colors.productID":
$qr .= " INNER JOIN(SELECT s.productID, GROUP_CONCAT";
$qr .= "(s.availSizes) AS size_list FROM availSizes AS s";
$qr .= " GROUP BY s.productID) AS sizes ON p.productID";
$qr .= " = sizes.productID";
$qr .= " INNER JOIN(SELECT avp.productID, avp.productImg";
$qr .= " FROM availImg AS avp ORDER BY avp.productID";
$qr .= " LIMIT 3) AS images ON images.productID = ";
$qr .= " p.productID";
$qr .= " WHERE p.productID = ?";
$qr .= " GROUP BY p.productID";

I finally figured it out, thanks to MYSQL Workbench! I ran the query on mysql workbench and counted the number of columns returned, and declared variables for each on the bind_result().

Related

I want to have data from 2 tables in MySQL ordered by date

I would like to get data from two tables in MySQL, ordered by date.
$sql = "
SELECT
items.*, invoice.*
FROM
items
JOIN
invoice
ON
items.user_id = invoice.buyer_id
WHERE
items.user_id = '$user_id'"
LIMIT
10
ORDER BY
date;
";
Try with:
$sql = "SELECT *";
$sql .= " FROM items, invoice";
$sql .= " WHERE items.user_id = invoice.buyer_id";
$sql .= " AND items.user_id = '$user_id'";
$sql .= " ORDER BY date DESC";
$sql .= " LIMIT 10";
Also it is better if you use it as a prepared statement instead of having the variable inside the SQL query to avoid SQL injection.

Find the average number for each user

First off, I am fairly new to coding. I try to do my due diligence before coming here for advice.
I am trying to write a function that will query the database for a users numbers and get the average for each user.
function getUserAverage($userID) {
//loop through user totals & calculate average for each user
$sql = "select p.userID, p.user, p.number ";
$sql .= "from " . DB_PREFIX . "numbers p ";
$sql .= "inner join " . DB_PREFIX . "users u on p.userID = u.userID ";
$sql .= "where u.userID = " . $user->userID . " ";
$sql .= "order by u.lastname, u.firstname";
$query = $mysqli->query($sql);
while ($row = $query->fetch_assoc()) {
//player average of numbers
$tba = ROUND(AVG(`number`),2);
}
$query->free;
return $tba;
}
The result I am hoping to get is something like:
user1 = 14.5
user2 = 35.8
user3 - 7.4
I have written code to get the average numbers for all, but the need is to get by individual user.
//Average Numbers
$sql_avgNum = "SELECT ROUND(AVG(`number`),2) AS `Average` \n"
. "FROM `" . DB_PREFIX . "numbers` \n";
$data = $mysqli->query($sql_avgNum);
$result_avgNum = mysqli_fetch_array($data);
echo ' <tr class="altrow"><td> Average Number: </td><td> ' .
$result_avgNum[0] . ' </td></tr>';
//End Average Numbers
for count average of individual data you must do it using group by. Further reference of group by is here:
I'm not very sure, but I think that this is what you're looking for:
function getUserAverage($userID) {
// loop through user totals & calculate average for each user
$sql = "SELECT p.userID, u.user, AVG(p.number) AS 'avarage' ";
$sql .= "FROM " . DB_PREFIX . "numbers p ";
$sql .= "INNER JOIN " . DB_PREFIX . "users u ON(p.userID = u.userID) ";
$sql .= "WHERE p.userID = " . $user->userID . " ";
$sql .= "GROUP BY p.userID ";
$sql .= "ORDER BY u.lastname, u.firstname";
$query = $mysqli->query($sql);
while ($row = $query->fetch_assoc()) {
//player average of numbers
$tba = $row['avarage'];
}
$query->free;
return $tba;
}

Where clause stopped working

I have this code that (without the WHERE, was working) How do I get it to work with the WHERE clause ?
I just need it to only list lines that is current and max 2 years ahead.
$SQL = "SELECT ";
$SQL .= "SUM(Bookings.Spots) as SUMSPOT, Trips.ID, Bookings.FK_ID, Trips.MaxSpots, ";
$SQL .= "Trips.Tripnr, Trips.StartDate, Trips.EndDate, Trips.StartLocation, ";
$SQL .= "Trips.DestinationDK, Trips.PricePerSpot ";
$SQL .= "FROM Trips WHERE Trips.EndDate >= NOW() AND Trips.EndDate < DATE_ADD(NOW(), INTERVAL 2 YEAR) ";
$SQL .= "LEFT JOIN Bookings on Bookings.FK_ID = Trips.ID ";
$SQL .= "GROUP BY Trips.ID, Bookings.FK_ID ORDER BY Trips.StartDate ASC ";
You need to add the WHERE clause after the LEFT JOIN and before the GROUP tag.
You can check the documentation here for more answers as to where you can put which keyword.

Working with output from joined tables with php oop

As part of my learning OOP PHP, I have made a database object that includes the following method:
public static function find_by_sql($sql="") {
global $database;
$result_set = $database->query($sql);
$object_array = array();
while ($row = $database->fetch_array($result_set)) {
$object_array[] = static::instantiate($row);
}
return $object_array;
}
and I can use this to retrieve and access data from a single table, however when I try to use it with joined tables, the object only gives me the data from the primary table e.g.
$sql = "SELECT s.name, m.id, m.firstName, m.lastName, m.dob";
$sql .= " FROM members AS m";
$sql .= " LEFT JOIN mbr_sections AS ms ON m.id = ms.member_id";
$sql .= " LEFT JOIN sections AS s ON ms.section_id = s.id";
$sql .= " ORDER BY s.organisation ASC, s.name ASC, m.lastName ASC, m.firstName ASC";
$sql .= " LIMIT {$per_page} ";
$sql .= " OFFSET {$pagination->offset()}";
$members = Member::find_by_sql($sql);
Using the above query the following code outputs nothing for the s.name field, but all the fields from the members table are correctly listed. I know that the MySQL query is accessing the data, as the ORDER BY statement is correctly sorting the output.
<?php foreach($members as $member): ?>
<tr>
<td><?php echo $member->name;?></td>
<td><?php echo $member->full_name();?></td>
<td><?php echo $member->getAge($member->dob);?></td>
<td>Edit</td>
<td>Delete</td>
</tr>
<?php endforeach; ?>
If I output $members with print_r($members) it only contains the data from the members table, how do I access the data retrieved from the other tables?
Thanks
You need to select them too here:
$sql = "SELECT s.name, m.id, m.firstName, m.lastName, m.dob";
$sql .= " FROM members AS m";
$sql .= " LEFT JOIN mbr_sections AS ms ON m.id = ms.member_id";
$sql .= " LEFT JOIN sections AS s ON ms.section_id = s.id";
$sql .= " ORDER BY s.organisation ASC, s.name ASC, m.lastName ASC, m.firstName ASC";
$sql .= " LIMIT {$per_page} ";
$sql .= " OFFSET {$pagination->offset()}";
$members = Member::find_by_sql($sql);
You only selected name, id, firstName, lastName and dob.
Here is an example:
$sql = "SELECT s.name, m.id, m.firstName, m.lastName, m.dob, mbr_sections.field_you_want, sections.*";

MySQL left join not working with AS keyword

I like to use self explaining names for associative selects, and sometimes it's even mandatory to avoid duplicates, so I use the AS keyword alot. But it's giving me some trouble with left joins.
This works:
$sql = "SELECT *,
projects.id as projects_id
FROM projects";
$sql .= " LEFT JOIN".
" (SELECT
projectfiles.id as projectfiles_id,
projectfiles.fileID as projectfiles_fileID,
projectfiles.projectID as projectfiles_projectID
FROM projectfiles
) AS projectfiles".
" ON projects.id = projectfiles_projectID";
However now I end up with useless data from projects, because it also picks up the fields userID and name, which I don't need. It's also picking up the id twice.
So I tried changing it to;
$sql = "SELECT
projects.id as projects_id
FROM projects";
With the ON line becoming
" ON projects_id = projectfiles_projectID";
But that gave the error Unknown column projects_id
So I tried
" ON projects.projects_id = projectfiles_projectID";
But still the same error
I then started experimenting, and tried (as a test)
$sql = "SELECT id,name,userID FROM projects";
$sql .= " LEFT JOIN".
" (SELECT
projectfiles.id as projectfiles_id,
projectfiles.fileID as projectfiles_fileID,
projectfiles.projectID as projectfiles_projectID
FROM projectfiles
) AS projectfiles".
" ON projects.id = projectfiles_projectID";
And to my surprise, the LEFT JOIN didn't seem to pick up anything at all.
Code:
$sql = "SELECT id,name,userID FROM projects";
$sql .= " LEFT JOIN".
" (SELECT
projectfiles.id as projectfiles_id,
projectfiles.fileID as projectfiles_fileID,
projectfiles.projectID as projectfiles_projectID
FROM projectfiles
) AS projectfiles".
" ON projects.id = projectfiles_projectID";
$res = mysql_query($sql);
if(!$res) die(mysql_error());
if(mysql_num_rows($res) > 0)
{
$rownum = 0;
while($row = mysql_fetch_assoc($res))
{
print_r($row);
echo "<br/><br/>";
$rownum++;
}
}
Output:
Which is weird because there is only one row in projects but 3 in projectfiles with that projectID... what am I doing wrong?
To select only from the projectfiles table:
$sql = "SELECT projectfiles.*,
projects.id as projects_id
FROM projects";
// rest of the code is the same
Update
$sql = "SELECT projectfiles.* FROM projects";
// rest of the code is the same
Use short form of the query:
$sql = "SELECT projects.id,projects.name,projects.userID FROM projects LEFT JOIN
projectfiles ON projects.id = projectfiles.projectID";
SELECT p.*, pf.id, pf.fileId
FROM projects p LEFT JOIN projectfiles pf
on p.id = pf.projectID
You can use "as" to do as you will then. No need for a subselect.
$sql = "SELECT p.id,p.name,p.userID FROM projects p";
$sql .= " LEFT JOIN".
" projectfiles pf ".
" ON p.id = p.projectID";
$sql = "SELECT prj.id as prjId,
prj.name as prjName,
prj.userID as prjUid,
pf.id as pfId,
pf.fileID as pfFileId,
pf.projectID as pfProjecId
FROM projects as prj
LEFT JOIN projectfiles AS pf
ON prj.id = pf.projectID";

Categories