Queries in loop taking too much time to execute - php

I am trying to update data with Ajax and PHP. The following script updating data, But its taking too much time to run.
PHP
$groupId = $_POST['group_id'];
$Id_array = $_POST['Id'];
$result_array = $_POST['result'];
$data = array();
if(count($_POST['data']) > 0 && !empty ($_POST['data'])){
foreach($_POST['data'] as $key => $array){
$row = array();
$row['team_id'] = intval($array['team_id']);
$row['Note'] = strip_tags(trim(strval($array['Note'])));
$data[$key] = $row;
}
for ($i = 0; $i < count($Id_array); $i++) {
$Id = intval($Id_array[$i]);
$result = strip_tags(trim(strval($result_array[$i])));
$sql1 = $db->prepare("UPDATE teams SET result = :result WHERE id = :id ");
foreach($data as $key => $array){
$sql1 ->execute(array(':result' => $result, ':id' => $Id));
}
$sql2 = $db->prepare("UPDATE teams SET note = :note WHERE team_id = :teamid AND group_id = :group_id");
foreach($data as $key => $array){
$sql2->execute(array(':note' => $array['Note'], ':teamid' => $array['team_id'], ':group_id' => $groupId ));
}
Network Timing

You don't need this loop:
foreach($data as $key => $array){
$sql1 ->execute(array(':result' => $result, ':id' => $Id));
}
It's updating the same ID repeatedly, since $Id doesn't change in the loop. Just do:
$sql1->execute(array(':result' => $result, ':id' => $Id));
once.
You can also get some small improvements by doing:
$sql1 = $db->prepare("UPDATE teams SET result = :result WHERE id = :id ");
$sql2 = $db->prepare("UPDATE teams SET note = :note WHERE team_id = :teamid AND group_id = :group_id");
just once, before any of the loops.
Another problem is that you have this loop:
foreach($data as $key => $array){
$sql2->execute(array(':note' => $array['Note'], ':teamid' => $array['team_id'], ':group_id' => $groupId ));
}
inside the for() loop, but it doesn't use any of the variables that change each time through the loop. So it's re-executing all the same queries for each ID in $Id_array.
Take it out of the loop.
With all these changes, the code now looks like:
$groupId = $_POST['group_id'];
$Id_array = $_POST['Id'];
$result_array = $_POST['result'];
$sql1 = $db->prepare("UPDATE teams SET result = :result WHERE id = :id ");
$sql2 = $db->prepare("UPDATE teams SET note = :note WHERE team_id = :teamid AND group_id = :group_id");
$data = array();
if(count($_POST['data']) > 0 && !empty ($_POST['data'])){
foreach($_POST['data'] as $key => $array){
$row = array();
$row['team_id'] = intval($array['team_id']);
$row['Note'] = strip_tags(trim(strval($array['Note'])));
$data[$key] = $row;
}
foreach ($Id_array as $i => $Id) {
$Id = intval($Id);
$result = strip_tags(trim(strval($result_array[$i])));
$sql1 ->execute(array(':result' => $result, ':id' => $Id));
}
foreach($data as $key => $array){
$sql2->execute(array(':note' => $array['Note'], ':teamid' => $array['team_id'], ':group_id' => $groupId ));
}
}

I would use a transaction instead of auto committing in a loop.
So,
//PDO::beginTransaction ( void )
$dbh->beginTransaction();
foreach () {
$smt->exec();
}
//PDO::commit ( void )
$dbh->commit();
Also, you only need to prepare a statement one time since you're binding your variables in the execute function, so try keeping any prepare statements out of a loop.
This should help with some of the overhead of the query in the loop.

Related

UPDATE record serialized - php mysql

I have this problem, I have to update a record of a table that has the values of a serialized column. the call to the function works and passes the data correctly. I can enter the record, but I can not update. This is my code:
public function update($user_id, $array_check)
{
$arrayB = array();
$array_check = unserialize($array_check);
foreach ($array_check $key => $value) {
if($value["id"] == $array_check){
$idRow = $value["id"];
if($value["value"] == "0"){
$valueRow = "1";
}else{
$valueRow = "0";
}
}else{
$idRow = $value["id"];
$valueRow = $value["value"];
}
$row = array("id" => $idRow, "value" => $valueRow);
$arrayB[] = $row;
}
$stmt = $this->_db->prepare('UPDATE data_docs SET docs_selected = :docs_selected WHERE user_id = :user_id');
$row = $stmt->execute(array(':user_id' => $user_id, ':docs_selected' => serialize($arrayB) ) );
return $arrayB;
}
edit.
Replace this:
$stmt = $this->_db->prepare('UPDATE data_docs SET docs_selected = :docs_selected WHERE user_id = :user_id);
with:
$deseralized = serialize($arrayB);
$stmt = $this->_db->prepare('UPDATE data_docs SET docs_selected = '$deseralized ' WHERE user_id = '$user_id');

Datasource not available within second while loop

I have the following php code:
$user_id = $user["id_user_key"];
$stmt = $db->prepare("CALL spGetUserProducts(?)");
$stmt->bind_param('i', $user_id);
$stmt->execute();
$result = $stmt->get_result();
$data = array();
while($row = $result->fetch_assoc()) {
$row_array = array();
$row_array["id"] = $row["id"];
$row_array["pname"] = $row["pname"];
$row_array["picon"] = $row["picon"];
$row_array["menuItems"] = array();
$product = $row["id"];
//loop
$result_opt = $db->query("CALL spGetUserProductViews($user_id, $product)");
while ($opt_fet = $result_opt->fetch_assoc()) {
$row_array["menuItems"][] = array(
"id" => $opt_fet["id"],
"vname" => $opt_fet["vname"],
"isheader" => $opt_fet["isheader"]
);
}
array_push($data, $row_array);
}
$stmt->close();
echo json_encode($data);
The first loop can get a hold of $db, in other words: the first prepared statement is being excecuted and gives me results. The second one:
$result_opt = $db->query("CALL spGetUserProductViews($user_id, $product)");
gives me false. When I try this statement outside the loop, it does work.
Any thoughts ont his?
I found out that mysqli can't handle two simultaneous queries because mysqli uses unbuffered queries by default. Now, I could have dived into this (for example make use of $stmt->store-result()), but I also realized that I would like to keep the load on my database to a minimum.
My solution:
$data = array();
$user_id = $user["id_user_key"];
//menus -> products
$stmt = $db->prepare("CALL spGetUserProducts(?)");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$menus = array();
while($row = $result->fetch_assoc()) {
$menus[] = $row;
}
$stmt->close();
//items -> views
$stmt = $db->prepare("CALL spGetUserProductViews(?)");
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$items = array();
while($row = $result->fetch_assoc()) {
$items[] = $row;
}
$stmt->close();
//generate object
//loop menus
foreach($menus as $m){
$row_array = array();
$row_array["id"] = $m["id"];
$row_array["pname"] = $m["pname"];
$row_array["picon"] = $m["picon"];
$row_array["menuItems"] = array();
//loop items
foreach($items as $i) {
if($m["id"] == $i["id_product"]) {
$row_array["menuItems"][] = array(
"id" => $i["id"],
"vname" => $i["vname"],
"isheader" => $i["isheader"]
);
}
}
array_push($data, $row_array);
}
echo json_encode($data);
So now I first generate arrays out of the two objects. then I do a foreach over the menus and then over the items. When the $menu["id"] equals $items["id_product"] then the array with items for that specific menu is being generated.
EDIT
After the data has been pulled from the database I first have to do a check wether or not the array contains data:
if(!empty($menus) && !empty($items)) {
foreach ($menus as $m) {
$row_array = array();
$row_array["id"] = $m["id"];
$row_array["pname"] = $m["pname"];
$row_array["picon"] = $m["picon"];
$row_array["menuItems"] = array();
//loop items
foreach ($items as $i) {
if ($m["id"] == $i["id_product"]) {
$row_array["menuItems"][] = array(
"id" => $i["id"],
"vname" => $i["vname"],
"isheader" => $i["isheader"]
);
}
}
array_push($data, $row_array);
}
}

foreach loop with PHP and PDO

this mysql update:
function updateOrder($id_array){
$count = 1;
foreach ($id_array as $id){
$update = mysqli_query($this->connect,"UPDATE `table_name` SET `order_id` = $count WHERE id = $id");
$count ++;
}
return true;
}
i'll change to PDO , this my write code but can work .
but that is not reflected in the db
function update($id_array,$_table){
$query = "UPDATE `table_name` SET `order_id` = ? WHERE id = ?";
$stmt = $this->conn->prepare($query);
$count = 1;
foreach ($id_array as $id) {
$stmt->execute(array(':$count' => $count, ':id' => $id));
$count ++;
}
return true;
}
call funtion :
$idArray = explode(",",$_POST['ids']);<br>
$db->update($idArray);
use:
$stmt->execute(array(':count' => $count, ':id' => $id));
instead of
$stmt->execute(array(':$count' => $count, ':id' => $id));
:$count to :count

Add new array key inside function

I have an array that is populated by a mysql_fetch_assoc. After the array is populated by the columns I want from the database, I would like to add another key to the array, using values that I obtain earlier in the function. I tried to accomplish this with a foreach loop, but my function is not returning the array. Where have I gone wrong?
//calculates payout
function calculate_payout($id){
$result = mysql_query("SELECT `result` FROM `bets` WHERE `id` = {$id}");
echo mysql_error();
$wager_total = mysql_query("SELECT SUM(`wager_amount`) AS `wager_total` FROM `wagers` WHERE `id` = '{$id}'");
$correct_wager_total = mysql_query("SELECT SUM(`wager_amount`) AS `correct_wager_total` FROM `wagers` WHERE `id` = '{$id}' AND `wager_option` = '{$result}'");
echo mysql_error();
$incorrect_wager_total = $wager_total - $correct_wager_total;
$sql = " SELECT * FROM `wagers` WHERE `id` = '{$id}' AND `wager_option` = '{$result}'";
echo mysql_error();
$data = mysql_query($sql);
$rows = array();
while(($row = mysql_fetch_assoc($data)) !== false){
$rows[] = array(
'bet_id' => $row['bet_id'],
'id' => $row['id'],
'wager_amount' => $row['wager_amount']
);
}
foreach ($rows as $p_row){
$payout = $p_row['wager_amount'] / $incorrect_wager_total;
$payout = $p_row['wager_amount'] + $payout;
$p_row['payout'] = $payout;
}
return $p_row;
}
The problem is that $p_row is a copy of the row in the array, so modifying it in the loop doesn't have any effect on the original array.
You can fix this by using a reference in the foreach:
foreach ($rows as &$p_row)
Or you can just do this as you're creating the $rows array in the while loop:
while ($row = mysql_fetch_assoc($data)) {
$new_row = array(
'bet_id' => $row['id'],
'id' => $row['id'],
'wager_amount' => $row['wager_amount'],
'payout' => $row['wager_amount'] / $incorrect_wager_total + $row['wager_amount']
);
Also, your return statement is wrong, it should be return $rows; to return the whole array; return $p_row will just return the last row of the array.

Yii: Using GROUP BY Clause

I want to implement GROUP BY clause of SQL using Yii. Here I faced problem of returning only first row instead of all rows.
$connection = Yii::app()->db;
$sql = "SELECT group_name FROM `authitem` GROUP BY group_name";
$command = $connection->createCommand($sql);
$row = $command->queryRow();
print_r($row);
$res = array();
foreach ($row as $key => $val) {
$res[] = array('label' => $key, 'value' => $val);
}
print_r($res);
instead of
$row = $command->queryRow();
try like this,
$row = $command->queryAll();

Categories