PHP/Mysql: optimize query - php

I have the following script that retrieve numbers from 2 tables, make a sum, and the value is updated into a 3th table.
$query = "SELECT (SELECT SUM(net_amount) FROM fin_costos WHERE month='1' AND group_of_costos='general' AND year_analysis='2014' ) +
(SELECT SUM(net_amount) FROM em2_fin_costs WHERE month='1' AND group_of_costos='general' AND year_analysis='2014') AS total";
$result = mysqli_query($mysqli,$query);
while($row = mysqli_fetch_array($result)){$valor_final = $row['total']; }
$query_update="UPDATE fusion_analysis SET jan='$valor_final' WHERE year_for_analysis='2014' AND item_for_analysis='general' AND category='general'";
$result = mysqli_query($mysqli,$query_update);
I need to run the same script for each month of the year. Everything is exaclty the same except the variable 'month' that changes from 1 to 12 and the SET in UPDATE where the value is uploaded for each month ('jan','feb', 'mar'...etc)
I'm currently just copying and pasting the same script changing this few parameters but I believe there is a smarter way to do this in less lines of code I have

See date function of PHP:
$query = "SELECT (SELECT SUM(net_amount)"
. " FROM fin_costos"
. " WHERE month='".date('n')."'"
." AND group_of_costos='general' AND year_analysis='".date("Y")."' ) +"
."(SELECT SUM(net_amount) FROM em2_fin_costs WHERE month='".date('n')."'"
. " AND group_of_costos='general' AND year_analysis='".date("Y")."') AS total";
$query_update="UPDATE fusion_analysis"
. " SET `". strtolower(date('M'))."`='$valor_final'"
. " WHERE year_for_analysis='".date("Y")."'"
. " AND item_for_analysis='general'"
. " AND category='general'";
NOTE:
Y - A full numeric representation of a year, 4 digits like 2014
n - Numeric representation of a month, without leading zeros 1 - 12
M - A short textual representation of a month, three letters Jan through Dec
For month as short textual I've used the strtolower function to make it lowercase.
UPDATE
Based on OP comment:
for ($i = 1; $i <= 12; $i++) {
$query = "SELECT (SELECT SUM(net_amount)"
. " FROM fin_costos"
. " WHERE month='" . $i . "'"
. " AND group_of_costos='general' AND year_analysis='" . date("Y") . "' ) +"
. "(SELECT SUM(net_amount) FROM em2_fin_costs WHERE month='" . $i . "'"
. " AND group_of_costos='general' AND year_analysis='" . date("Y") . "') AS total";
$result = mysqli_query($mysqli, $query);
$row = mysqli_fetch_assoc($result);
$valor_final = $row['total'];
$monthName = strtolower(date('M', strtotime(date("Y") . "-" . str_pad($month,2, "0", STR_PAD_LEFT) . "-" . date("01") )));
$query_update = "UPDATE fusion_analysis"
. " SET `" . $monthName . "`=' " . $valor_final . "'"
. " WHERE year_for_analysis='" . date("Y") . "'"
. " AND item_for_analysis='general'"
. " AND category='general'";
mysqli_query($mysqli, $query_update);
}

Related

While doesnt give me more trainers

I'm trying to make a map with available gyms that also shows what exercises they have. So it looks like this:
Name Gym
Open spots: (number)
Logo image of Gym
Time of excercise.
Image of a dumbel for example
Trainer
The part from Time of exercise til Trainer needs to show more than one, I got like 6 exercises with 6 trainers, and 6 times and 6 different images of exercises to show. I store those in a database; but they don't show up.
Here my code:
$sql = "SELECT * FROM forts";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
echo "[";
$output = array();
while($row = $result->fetch_assoc()) {
$url = preg_replace("/^http:/i", "https:", $row['url']);
$sqlmon = "SELECT * FROM gym_trainers WHERE fort_id = " . $row['id'];
$resultmon = $mysqli->query($sqlmon);
$mon = $resultmon->fetch_assoc();
$sqlextra = "SELECT * FROM extrainfo WHERE fort_id = " . $row['id'] . " ORDER BY last_modified DESC";
$resultextra = $mysqli->query($sqlextra);
$extra = $resultextra->fetch_assoc();
array_push($output, '
{
"id": "' . $row['id'] . '",
"name": "' . htmlspecialchars($row['name']) . '",
"image": "' . $url . '",
"team": "' . $team . '",
"spots": ' . $extra['spots'] . ',
"exer_time": ' . $mon['time_exerise'] . ',
"trainer": "' . htmlspecialchars($mon['trainer_name']) . '",
"exercise_id": ' . $mon['exercise_id'] . ',
"lat": ' . $row['lat'] . ',
"lng": ' . $row['lon'] . '
}
');
}
echo implode(",", $output);
echo "]";
I think something with this part needs to change, but don't know what:
"exer_time": ' . $mon['time_exerise'] . ',
"trainer": "' . htmlspecialchars($mon['trainer_name']) . '",
"exercise_id": ' . $mon['exercise_id'] . ',
The specific problem is that you fetch only 1 record from the gym_trainers table (the $resultmon->fetch_assoc() is not in a separate loop).
The wider problem is that you do not use joins. The 3 separate sql queries could be written as
select *
from forts f
left join gym_trainers g on f.id=g.fort_id
left join extrainfo e on f.id=g.fort_id
In this case you would need a single loop and within the single loop you track if the fort changes.

Subquery calculation error?

Why is this query not working?
$query = ("SELECT * FROM
(SELECT *, (
(((endingLatitude - " . $h . ")(endingLatitude - " . $h . "))
/" . pow($r1, 2) . ")
+
((endingLongitude - " . $k . ")(endingLongitude - " . $k . "))
/" . pow($r2, 2) . "
) AS point2
FROM (SELECT *, ((
(
((startingLatitude - " . $h . ")(startingLatitude - " . $h . "))
/" . pow($r1, 2) . ")
+
((startingLongitude - " . $k . ")(startingLongitude - " . $k . "))
/" . pow($r2, 2) . "))
AS point1
FROM (SELECT * FROM trips WHERE distance >='" . ($distance * .25) . "') as query1)
as query2) as query3 WHERE point1 <= 1 AND point2 <= 1 LIMIT 0 , 10;");
$result = mysqli_query($con, $query);
$h and $k is the ellipses x and y coordinates respectively. I am using a formula found here to calculate whether or not the two points, (startingLat,startingLong) and (endingLat,endingLong) are within an ellipse with vertical height $r1 and horizontal height $r2. I am also limiting the rows that I search to rows that have a distance cell value of greater than $distance * .25.
I think it might have something to do with a parenthesis error or something to do with the way I am sub querying/performing my calculations.
Using
die(mysqli_error($con));
returns an error of You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(endingLatitude - 36.9564753)) /796.842964388) + ((endingLongitud' at line 3
I believe you have to use Mysql multiplication arithmetic operator, *.
https://dev.mysql.com/doc/refman/5.0/en/arithmetic-functions.html#operator_times
Instead of:
(endingLatitude - " . $h . ")(endingLatitude - " . $h . ")
Do this...
(endingLatitude - " . $h . ") * (endingLatitude - " . $h . ")

Optimizing PHP script

I have a working script that selects image fields in all tables and empty their values if the physical file doesnt exist.
$query1 = "SELECT table_name,column_name
FROM information_schema.columns
WHERE table_schema='schemaname' AND column_name like '%image%' or column_name='video'";
$result1 = mysql_query($query1) or die(mysql_error() . " -- " . $query1);
while($row1 = mysql_fetch_row($result1)){
if (!strpos($row1[0],'backup') > 0){
$sql = "Select COLUMN_NAME FROM information_schema.columns WHERE TABLE_NAME = '".$row1[0]."' AND EXTRA = 'auto_increment'";
$resultcol = mysql_query($sql);
$rowcol = mysql_fetch_row($resultcol);
$query2 = "SELECT " . $row1[1] . ", " .$rowcol[0] . "
FROM " . $row1[0] . "
WHERE " . $row1[1] . " != '' AND " . $row1[1] . " IS NOT NULL
";
echo $query2 . "<br>";
$result2 = mysql_query($query2) or die(mysql_error() . " -- " . $query2);
while ($rowdb = mysql_fetch_row($result2)){
if (!strpos($rowdb[0],'facebook') > 0 && !file_exists($img_root.'/'.$rowdb[0])){
$sql = "UPDATE ".$row1[0]." SET ". $row1[1] . " = '' WHERE " . $rowcol[0]. "= ".$rowdb[1];
echo $sql . "<br><br>";
$delete_count++;
//mysql_query("UPDATE ".$row1[0]." SET ". $row1[1] . " = '' WHERE id = ".$row1["id"]);
}
}
}
}
The script is working fine, but it takes time though, I was wondering if there is a smarter way (more optimized) to get the same function ? Thanks
You have several options.
The first, and IMHO the best option - is to use an ORM -
I recommend Idiorm, Doctrine, or Propel.
Then, you would use something like (in idiorm) fetch_all and loop through that, instead of through the mysql_fetch_row()
Second, you should switch to mysqli -- the functions you are using are deprecated in PHP5.5
Third -- you could just use either mysql_fetch_array or mysql_fetch_all (I'm not sure, but I would be on the latter)
The key thing here is:
Do not loop mysql functions.
Performance wise the problem is that you are looping through a result set, and performing queries for each row.
However with your output it is difficult to eliminate this. Otherwise you might be able to do the whole script in a single SQL statement.
Minimal clean up to just remove one of the selects:-
<?php
$query1 = "SELECT a.table_name, a.column_name, b.COLUMN_NAME AS auto_inc_col
FROM information_schema.columns a
INNER JOIN information_schema.columns b
ON a.table_name = b.table_name AND b.EXTRA = 'auto_increment'
WHERE table_schema='schemaname' AND column_name like '%image%' or column_name='video'";
$result1 = mysql_query($query1) or die(mysql_error() . " -- " . $query1);
while($row1 = mysql_fetch_assoc($result1))
{
if (!strpos($row1['table_name'],'backup') > 0)
{
$query2 = "SELECT " . $row1['column_name'] . ", " .$row1['auto_inc_col'] . "
FROM " . $row1['table_name'] . "
WHERE " . $row1['column_name'] . " != '' AND " . $row1['column_name'] . " IS NOT NULL
";
echo $query2 . "<br>";
$result2 = mysql_query($query2) or die(mysql_error() . " -- " . $query2);
while ($rowdb = mysql_fetch_row($result2))
{
if (!strpos($rowdb[0],'facebook') > 0 && !file_exists($img_root.'/'.$rowdb[0]))
{
$sql = "UPDATE ".$row1['table_name']." SET ". $row1['column_name'] . " = '' WHERE " . $row1['auto_inc_col']. "= ".$rowdb[1];
echo $sql . "<br><br>";
$delete_count++;
//mysql_query("UPDATE ".$row1['table_name']." SET ". $row1['column_name'] . " = '' WHERE id = ".$row1["id"]);
}
}
}
}
?>

How to Sort users who voted by number of Published links

problems with a lot of users have the names of long in who liked for this Story
So How can I sort users by number of published links in who voted.
in libs/htm1.php
function who_voted($storyid, $avatar_size){
// this returns who voted for a story
// eventually add support for filters (only show friends, etc)
global $db;
if (!is_numeric($storyid)) die();
$sql = 'SELECT ' . table_votes . '.*, ' . table_users . '.* FROM ' . table_votes . ' INNER JOIN ' . table_users . ' ON ' . table_votes . '.vote_user_id = ' . table_users . '.user_id WHERE (((' . table_votes . '.vote_value)>0) AND ((' . table_votes . '.vote_link_id)='.$storyid.') AND (' . table_votes . '.vote_type= "links")) AND user_level<>"god" AND user_level<>"Spammer"';
//echo $sql;
$voters = $db->get_results($sql);
$voters = object_2_array($voters);
foreach($voters as $key => $val){
$voters[$key]['Avatar_ImgSrc'] = get_avatar($avatar_size, "", $val['user_login'], $val['user_email']);
}
return $voters;
I found these lines in topusers.php, but not for a friendly experience in writing function correctly
case 2: // sort users by number of published links
$select = "SELECT user_id, count(*) as count ";
$from_where = " FROM " . table_links . ", " . table_users . " WHERE link_status = 'published' AND link_author=user_id AND user_level NOT IN ('god','Spammer') AND (user_login!='anonymous' OR user_lastip) GROUP BY link_author";
$order_by = " ORDER BY count DESC ";
break;

PHP Not Inserting Variable Into mySQL Query

I am having trouble getting one of my variable to be successfully inserted into my mySQL query. Here is the query string:
$strShipMethodInfo = "SELECT BAMMDD, BAYY, BAXXX, ORDNUM, SHPNUM, \"SHIPMENT METHOD\", \"SHIPMENT STATUS\" FROM SHPPMTHD WHERE BAMMDD = " . $BAMMDD . " AND BAYY = " . $BAYY . " AND BAXXX = " . $BAXXX . " AND SHPNUM = " . $arrShippingInfo[$x]['SHPNUM'] . " AND ORDNUM = '" . $ORDNUM . "' ORDER BY SHPNUM";
I am using $arrShippingInfo[$x]['SHPNUM'] in another query that is very similar, and it is putting the variable in that one. However, when I do it with this query, it comes back as blank. All the other values (BAMMDD, BAYY, BAXXX, etc.) are successfully put in, but the variable for SHPNUM does not get put in.
I have tried everything I can think of, thinking that it might be a quote in the wrong place, but I have been unsuccessful. Could anyone please help me figure this out? Thanks.
EDIT: I did a print_r on the string, and it printed twice... once with the SHPNUM correctly inserted and once with it blank. Turns out it was a logic error in the for loop I was using (I needed to run the query for each shipment in the order). < somehow got changed to <= so once I changed that it worked. Thank you everyone for your responses.
I would say there is something wrong with how you are accessing that array value, either with the $x variable, or in how you are passing in the raw array value to the string (hard to say without the rest of your code: try assigning it to $SHPNUM and putting $SHPNUM into the statement?).
Within your code try running an:
echo $x; echo $arrShippingInfo[$x]['SHPNUM'];
var_dump($arrShippingInfo);
and you should be able to find the issue.
Using dummy data with your statement and running that code through on my end as:
<?php
$BAMMDD = 'bamddd';
$BAYY = 'BAYY';
$BAXXX = 'BAXXX';
$arrShippingInfo[0]['SHPNUM'] = '54';
$ORDNUM = 555;
$x = 0;
$strShipMethodInfo = "SELECT BAMMDD, BAYY, BAXXX, ORDNUM, SHPNUM, \"SHIPMENT METHOD\", \"SHIPMENT STATUS\" FROM SHPPMTHD WHERE BAMMDD = " . $BAMMDD . " AND BAYY = " . $BAYY . " AND BAXXX = " . $BAXXX . " AND SHPNUM = " . $arrShippingInfo[$x]['SHPNUM'] . " AND ORDNUM = '" . $ORDNUM . "' ORDER BY SHPNUM";
echo "<pre>$strShipMethodInfo</pre>";
?>
Produces:
SELECT BAMMDD, BAYY, BAXXX, ORDNUM, SHPNUM, "SHIPMENT METHOD",
"SHIPMENT STATUS" FROM SHPPMTHD WHERE BAMMDD = bamddd AND BAYY = BAYY
AND BAXXX = BAXXX AND SHPNUM = 54 AND ORDNUM = '555' ORDER BY SHPNUM
$strShipMethodInfo = "SELECT BAMMDD, BAYY, BAXXX, ORDNUM, SHPNUM, \"SHIPMENT METHOD\", \"SHIPMENT STATUS\" FROM SHPPMTHD WHERE BAMMDD = '" . $BAMMDD . "' AND BAYY = '" . $BAYY . "' AND BAXXX = '" . $BAXXX . "' AND SHPNUM = '" . $arrShippingInfo[$x]['SHPNUM'] . "' AND ORDNUM = '" . $ORDNUM . "' ORDER BY SHPNUM";
Added quotes(') in the where condtion

Categories