I've never used mysqli_multi_query before and it's boggling my brain, any examples I find on the net aren't helping me to figure out exactly what it is I want to do.
Here is my code:
<?php
$link = mysqli_connect("server", "user", "pass", "db");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$agentsquery = "CREATE TEMPORARY TABLE LeaderBoard (
`agent_name` varchar(20) NOT NULL,
`job_number` int(5) NOT NULL,
`job_value` decimal(3,1) NOT NULL,
`points_value` decimal(8,2) NOT NULL
);";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`, `job_number`, `job_value`, `points_value`) SELECT agent_name, job_number, job_value, points_value FROM jobs WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`) SELECT DISTINCT agent_name FROM apps WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "SELECT agent_name, SUM(job_value), SUM(points_value) FROM leaderboard GROUP BY agent_name ORDER BY SUM(points_value) DESC";
$i = 0;
$agentsresult = mysqli_multi_query($link, $agentsquery);
while ($row = mysqli_fetch_array($agentsresult)){
$number_of_apps = getAgentAppsWeek($row['agent_name'],$weeknum,$current_year);
$i++;
?>
<tr class="tr<?php echo ($i & 1) ?>">
<td style="font-weight: bold;"><?php echo $row['agent_name'] ?></td>
<td><?php echo $row['SUM(job_value)'] ?></td>
<td><?php echo $row['SUM(points_value)'] ?></td>
<td><?php echo $number_of_apps; ?></td>
</tr>
<?php
}
?>
All I'm trying to do is run a multiple query and then use the final results from those 4 queries and put them into my tables.
the code above really doesn't work at all, I just get the following error:
Warning: mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given in C:\xampp\htdocs\hydroboard\hydro_reporting_2010.php on line 391
any help?
From the manual: mysqli_multi_query()
returns a bool
indicating success.
To retrieve the resultset from the first query you can use mysqli_use_result() or mysqli_store_result(). All subsequent query results can be processed using mysqli_more_results() and mysqli_next_result().
Here is a function that returns the last result of a multi-query:
function mysqli_last_result($link) {
while (mysqli_more_results($link)) {
mysqli_use_result($link);
mysqli_next_result($link);
}
return mysqli_store_result($link);
}
Usage:
$link = mysqli_connect();
$query = "SELECT 1;";
$query .= "SELECT 2;";
$query .= "SELECT 3";
mysqli_multi_query($link, $query);
$result = mysqli_last_result($link);
$row = $result->fetch_row();
echo $row[0]; // prints "3"
$result->free();
mysqli_close($link);
Okay after some fiddling around, trial and error and taking reference from another post that I came across in a Google search I've managed to solve my problem!
Here's the new code:
<?php
$link = mysqli_connect("server", "user", "pass", "db");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$agentsquery = "CREATE TEMPORARY TABLE LeaderBoard (
`agent_name` varchar(20) NOT NULL,
`job_number` int(5) NOT NULL,
`job_value` decimal(3,1) NOT NULL,
`points_value` decimal(8,2) NOT NULL
);";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`, `job_number`, `job_value`, `points_value`) SELECT agent_name, job_number, job_value, points_value FROM jobs WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "INSERT INTO LeaderBoard (`agent_name`) SELECT DISTINCT agent_name FROM apps WHERE YEAR(booked_date) = $current_year && WEEKOFYEAR(booked_date) = $weeknum;";
$agentsquery .= "SELECT agent_name, SUM(job_value), SUM(points_value) FROM leaderboard GROUP BY agent_name ORDER BY SUM(points_value) DESC";
mysqli_multi_query($link, $agentsquery) or die("MySQL Error: " . mysqli_error($link) . "<hr>\nQuery: $agentsquery");
mysqli_next_result($link);
mysqli_next_result($link);
mysqli_next_result($link);
if ($result = mysqli_store_result($link)) {
$i = 0;
while ($row = mysqli_fetch_array($result)){
$number_of_apps = getAgentAppsWeek($row['agent_name'],$weeknum,$current_year);
$i++;
?>
<tr class="tr<?php echo ($i & 1) ?>">
<td style="font-weight: bold;"><?php echo $row['agent_name'] ?></td>
<td><?php echo $row['SUM(job_value)'] ?></td>
<td><?php echo $row['SUM(points_value)'] ?></td>
<td><?php echo $number_of_apps; ?></td>
</tr>
<?php
}
}
?>
after sticking mysqli_next_result in there multiple times for each query it magically worked! yay! I understand why it works, because i'm telling it to skip to the next result 3 times, so it skips to the result for query #4 which is the one i want to use.
Seems a bit clunky to me though, there should just be a command for something like mysqli_last_result($link) or something if you ask me...
Thanks for the help rik and f00, I got there eventually :)
I would simplify what you're trying to do by creating a stored procedure which will produce the leader/agent stats and then just call it from your php (single call) as follows:
full script here : http://pastie.org/1451802
alternatively, you could probably combine your individual queries into a single select/group by statement.
see here : http://pastie.org/1451842
select
leaders.agent_name,
sum(leaders.job_value) as sum_job_value,
sum(leaders.points_value) as sum_points_value
from
(
select
agent_name,
job_number,
job_value,
points_value
from
jobs
where
year(booked_date) = 2011 and weekofyear(booked_date) = 2
union all
select distinct
agent_name,
0,0,0
from
apps
where
year(booked_date) = 2011 and weekofyear(booked_date) = 2
) leaders
group by
agent_name
order by sum_points_value desc;
drop procedure if exists list_leaders;
delimiter #
create procedure list_leaders
(
in p_year smallint unsigned,
in p_week tinyint unsigned
)
begin
create temporary table tmp_leaders(
agent_name varchar(20) not null,
job_number int unsigned not null default 0, -- note the default values
job_value decimal(3,1) not null default 0,
points_value decimal(8,2) not null default 0
)engine=memory;
insert into tmp_leaders (agent_name, job_number, job_value, points_value)
select agent_name, job_number, job_value, points_value from jobs
where year(booked_date) = p_year and weekofyear(booked_date) = p_week;
insert into tmp_leaders (agent_name) -- requires default values otherwise you will get nulls
select distinct agent_name from apps
where year(booked_date) = p_year and weekofyear(booked_date) = p_week;
select
agent_name,
sum(job_value) as sum_job_value,
sum(points_value) as sum_points_value
from
tmp_leaders
group by
agent_name order by sum_points_value desc;
drop temporary table if exists tmp_leaders;
end#
delimiter ;
call list_leaders(year(curdate()), weekofyear(curdate()));
<?php
ob_start();
try
{
$db = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);
if ($db->connect_errno)
throw new exception(sprintf("Could not connect: %s", $db->connect_error));
$sqlCmd = "call list_leaders(2011, 2)";
$result = $db->query($sqlCmd);
if(!$result) throw new exception(sprintf("Invalid query : %s", $sqlCmd));
if($db->affected_rows <= 0){
echo "no leaders found !";
}
else{
$leaders = $result->fetch_all(MYSQLI_ASSOC);
foreach($leaders as $ldr){
// do stuff
echo $ldr["agent_name"], "<br/>";
}
}
}
catch(exception $ex)
{
ob_clean();
echo sprintf("zomg borked - %s", $ex->getMessage());
}
if(!$db->connect_errno) $db->close();
ob_end_flush();
?>
Kinda simpler now - hope it helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With