Have PHP count rows with a query that is already using count(*)? - php

I have a subquery and I want to count the rows in PHP for MySQL. I am trying to fix old code and know that PDO is better and more secure and we will eventually rewrite all this code, but for now I need to just make it work. My problem is figuring out the command for the $total_employees to count the rows. This number will be used in a formula later. Is there a way to do it as 2 subqueries or rewriting it in the SQL statement other than just using php and mysql_fetch_row? I am trying to avoid multiple while loops. This is condensed from a bigger query for easier viewing.
while($rows=mysql_fetch_array($sqls)){
$cycle_id = $rows[cycle_id];
$sqls=("select subb.sqlcal AS sqlcalemp from
(select count(*) as sqlcal from dialogue_employees d_e,
dialogue_leaders d_l where
d_l.leader_group_id = d_e.leader_group_id and
d_l.cycle_id = $cycle_id) as subb");
$total_employees += $rows[sqlcalsemp];
This was the older code that worked before trying to update it:
while($rows=mysql_fetch_array($sqls)){
$cycle_id = $rows[cycle_id];
$sqlcalcemp=mysql_query("select count(*) from dialogue_employees d_e,
dialogue_leaders d_l where
d_l.leader_group_id = d_e.leader_group_id and
d_l.cycle_id = $cycle_id") or die(mysql_error());
$rowtotal = mysql_fetch_row($sqlcalcemp);
$total_employees += $rowtotal[0];

your looping through and looking at each cycle_id...
maybe try something like this to grab all counts for each cycle_id at once
select SUM(d_e.leader_group_id IS NOT NULL) as sqlcalemp,d_l.cycle_id
from dialogue_leaders d_l
left join dialogue_employees d_e
on d_l.leader_group_id = d_e.leader_group_id
group by d_l.cycle_id
http://sqlfiddle.com/#!9/4995b/4

Related

PHP/MYSQL query execution time optimisation

I am having a great deal of difficulty with this set of queries. I cannot find a way to speed up the second query at all. I've tried joining the the first query as a subquery on the second one, running through the first query results one by one and the current setup, all of which have proven extremely slow.
I would like to simply add a limit to the second query instead of this hocky stuff but our mysql version is too old to support it. For some reason it is also treating EXPLAINas a syntax error, which is unhelpful.
How can I reduce the execution time of this?
$limitQuery = $pdo->prepare("
SELECT r.supplier_option_code FROM third_party_raw_stock_price AS r ORDER BY r.id LIMIT 100
");
$limitQuery->execute();
$limitIds = $limitQuery->fetchAll();
$limitIds = implode("', '",array_column($limitIds, 'supplier_option_code'));
$limitQuery = null;
$linkColumn = 'supplier_code';
$thirdPartyId = 'FS';
$migrateQuery = $pdo->prepare("
UPDATE third_party_raw_stock_price AS r
JOIN options_new AS o
ON o.".$linkColumn." = r.supplier_option_code AND r.supplier_prefix = '".$thirdPartyId."'
JOIN third_party_config AS t
ON t.code = '".$thirdPartyId.""'
SET o.price = '989.99', o.cost_price_variation = '3.33', o.stock = '7'
WHERE r.supplier_option_code IN ('$limitIds')
");
$migrateQuery->execute([':config' => $thirdPartyId]);

Pull number of rows from a SQL query and put it in PHP as a variable?

This is 4 queries put into one. This is really old code and once I can make this work we can update it later to PDO for security. What I am trying to do is count rows from
select count(*) from dialogue_employees d_e,
dialogue_leaders d_l where
d_l.leader_group_id = d_e.leader_group_id
and use it in a formula where I also count how many rows from dialogue.status = 1.
The formula is on the bottom to create a percentage total from the results. This is PHP and MySQL and I wasn't sure the best way to count the rows and put them as a variable in php to be used in the formula on the bottom?
function calculate_site_score($start_date, $end_date, $status){
while($rows=mysql_fetch_array($sqls)){
$query = "
SELECT
dialogue.cycle_id,
$completecount = sum(dialogue.status) AS calculation,
$total_employees = count(dialogue_employees AND dialogue_leaders), dialogue_list.*,
FROM dialogue,
(SELECT * FROM dialogue_list WHERE status =1) AS status,
dialogue_employees d_e,
u.fname, u.lname, d_e.*
user u,
dialogue_list,
dialogue_leaders d_l
LEFT JOIN dialogue_list d_list
ON d_e.employee_id = d_list.employee_id,
WHERE
d_l.leader_group_id = d_e.leader_group_id
AND d_l.cycle_id = dialogue.cycle_id
AND u.userID = d_e.employee_id
AND dialogue_list.employee_id
AND site_id='$_SESSION[siteID]'
AND start_date >= '$start_date'
AND start_date <= '$end_date'";
$sqls=mysql_query($query) or die(mysql_error());
}
$sitescore=($completecount/$total_employees)*100;
return round($sitescore,2);
}
If you separate out your queries you will gain more control over your data. You have to be careful what your counting. It's pretty crowded in there.
If you just wanted to clean up your function you can stack your queries like this so they make more sense, that function is very crowded.
function calculate_site_score($start_date, $end_date, $status){
$query="select * from dialogue;";
if ($result = $mysqli->query($query))) {
//iterate your result
$neededElem = $result['elem'];
$query="select * from dialogue_list where status =1 and otherElem = " . $neededElem . ";";
//give it a name other than $sqls, something that makes sense.
$list = $mysqli->query($query);
//iterate list, and parse results for what you need
foreach($list as $k => $v){
//go a level deeper, or calculate, rinse and repeat
}
}
Then do your counts separately.
So it would help if you separate queries each on their own.
Here is a count example How do I count columns of a table

Speeding up my queries in PHP

I'm working on trying to speed up a webpage I have created. I know the issue is that I have a query within a query. I feel like there has to be a quicker way to accomplish the same results, but I'm running out of ideas. (My first attempt at this took 45 seconds for the page to load, now I'm down to about 6)
What I'm trying to do is pull run rate information from tables. I need to pull the correct startup and end of run rates from the runrate table, but all I have to go off of initially is the workcenter ID.
I feel like if the tables were set up a little bit better then it probably would've have been so difficult, but it's what I inherited and as a result I'm a bit stuck. I need to pull a month worth of data from each workcenter (about 15) where there can be as many as 4-5 runs each day... Quite a bit of data to process.
Here's the PHP code:
$qtotalStartup = mysql_query("
SELECT startup.recordID, startup.date, startup.time, runrate.rate AS temRate, runrate.formID
FROM jos_a_inproc_startup startup JOIN jos_a_runrate runrate ON startup.recordID = runrate.recordID
WHERE startup.workcenterId = $id AND runrate.rate > 0 AND runrate.formID = 1 AND startup.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)") or die(mysql_error());
$totalStartCtr = mysql_num_rows($qtotalStartup);
if ($totalStartCtr > 0) {
while($rtotalStartup = mysql_fetch_assoc($qtotalStartup)) {
$hours = 0;
$goalRate = 0;
$sumHrRR = 0;
$startDate = 0;
$startTime = 0;
$startupNum = $rtotalStartup['recordID'];
$goalRate = $rtotalStartup['temRate'];
$startDate = $rtotalStartup['date'];
$startTime = $rtotalStartup['time'];
$startTime = strtotime($startDate . ' ' . $startTime);
//now that we have all of the startup form info, we can move to the end of run information
//this query will retrieve the correct date, time, and ending run rate for us to use with our calculations.
$qtotalEOR = mysql_query("
SELECT eor.recordID AS eorRec, eor.date, eor.time, eor.startupid, runrate1.rate AS tempRate, runrate1.formID
FROM jos_a_inproc_eor eor JOIN jos_a_runrate runrate1 ON eor.recordID = runrate1.recordID
WHERE eor.startupid = $startupNum AND runrate1.rate > 0 AND runrate1.formID = 3") or die(mysql_error());
$totalEORCtr = mysql_num_rows($qtotalEOR);
if ($totalEORCtr > 0) {
while($rtotalEOR = mysql_fetch_assoc($qtotalEOR)) {
//reset the accumulator to 0 so we don't get extra 'bad' data.
$sumHrRR = 0;
$newGoalRate = 0;
$lastestDate = 0;
$latestTime = 0;
$eorNum = $rtotalEOR['eorRec'];
$latestDate = $rtotalEOR['date'];
$latestTime = $rtotalEOR['time'];
$latestTime = strtotime($latestDate . ' ' . $latestTime);
$sumHrRR= $rtotalEOR['tempRate'];
Any ideas would be greatly appreciated. I know it may be difficult to understand what I'm trying to get at without much more information, so let me know if you need to know anything else. Thanks.
Maby try using multiple JOINS like this one:
SELECT startup.recordID, startup.date, startup.time,
runrate.rate AS temRate, runrate.formID
-- stuff from second query
eor.recordID AS eorRec, eor.date AS eor_date,
eor.time AS eor_time, eor.startupid AS eor_startupid,
runrate1.rate AS eor_tempRate,
runrate1.formID AS runrate1_formID
FROM jos_a_inproc_startup startup
JOIN jos_a_runrate runrate ON startup.recordID = runrate.recordID
-- second query LEFT JOIN
LEFT JOIN jos_a_inproc_eor eor
ON eor.startupid = startup.recordID
LEFT JOIN jos_a_runrate runrate1
ON eor.recordID = runrate1.recordID
AND runrate1.rate > 0
AND runrate1.formID = 3
WHERE startup.workcenterId = $id
AND runrate.rate > 0
AND runrate.formID = 1
AND startup.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)
I don't know if I'm right but I think that you are also doing some aggregation work with results inside PHP. You could do it inside database using like sum() or avg() and GROUP BY. You will save some time when transfering smaller result set from database to server and time for looping and aggregating inside PHP. Also most of the time using JOIN is much faster than using queries in loop or even subqueries inside query.
You should also check if indexes are set on columns you search in. Also use EXPLAIN to check how query is executed.
you can use Mem-Cache techniques to make it much faster ,and try to make your queries the simpler that u can .. dont retrieve values that you dont use in your scripts ..
How many records are you typically dealing with as output? How big are the tables? Have you reviewed the indexes? Have you analyzed them recently (rebuilt them)?
Also, are you sending the data back to the browser using deflate? See:
http://httpd.apache.org/docs/2.2/mod/mod_deflate.html
Well, you could try using multiple INNER JOINs (see) and have only one query instead of one query inside a query, which greatly impacts on performance. You could try something like this, and tweaking it a little:
SELECT
startup.recordID AS startupRecordID,
startup.date AS startupDate,
startup.time AS startupTime,
runrate.rate,
runrate.formID,
eor.recordID AS eorRecordID,
eor.date AS eorDate,
eor.time AS eorTime,
eor.startupid AS eorStartupID
FROM jos_a_inproc_startup startup
INNER JOIN jos_a_runrate runrate
ON startup.recordID = runrate.recordID
INNER JOIN jos_a_inproc_eor eor
ON startup.recordID = eor.startupid
WHERE
startup.workcenterId = $id
AND runrate.rate > 0
AND runrate.formID = 1
AND startup.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)

How to query 2 tables

I need to sum the transactions in tblgl (tblgl.SUM(InMonthActual)) for a selection of cost centres (tblgl.CostCentreCode) where the following conditions are met:
tblgl.PeriodNumber = 2
tblgl.CostCentreCode = tblcostcentrehierarchy.CostCentreCode
WHERE tblcostcentrehierarchy.Level7 = "RWK312 CORPORATE"
tblgl.CostCentreCode = tblcostcentreallocations.CostCentreCode
WHERE tblcostcentreallocations.Username = "jonest"
At the moment I'm running 3 separate queries to create an array which is used in the next query.
Is there a way to do it in one (maybe using JOIN)?
I hope this query will fetch your desire data. Check and let me know if it works for you.
SELECT SUM(tb1.`InMonthActual`)
FROM `tblgl` as tb1
JOIN `tblcostcentrehierarchy` as tb2 ON tb1.`CostCetntreCode` = tb2.`CostCentreCode`
JOIN `tblcostcentreallocations` as tb3 ON tb1.`CostCetntreCode` = tb3.`CostCentreCode`
WHERE tb1.`PeriodNumber` = '2' AND tb2.`Level17` = "RWK312 CORPORATE" AND tb3.`Username` = "jonest"
Give it a try
SELECT SUM(tblgl.InMonthActual) FROM tblgl
INNER JOIN tblcostcentrehierarchy ON (tblgl.CostCentreCode = tblcostcentrehierarchy.CostCentreCode AND tblgl.PeriodNumber = 2)
INNER JOIN tblcostcentreallocations ON (tblgl.CostCentreCode = tblcostcentreallocations.CostCentreCode)
WHERE tblcostcentreallocations.Username = "jonest" AND tblcostcentrehierarchy.Level7 = "RWK312 CORPORATE"
GROUP BY tblgl.InMonthActual
Hope it works fine

Duplicate values returning from mySQL JOIN Statement. Help?

I am having a hard time creating a mySQL join statement.
The issue is that it seems to return the correct results, but it returns duplicates.
$result= mysql_query("SELECT Photos.Filename, Photos.Filetype
FROM Photos, PhotoUserTags
WHERE PhotoUserTags.User_ID IN ($friendlist) && PhotoUserTags.Photo_ID = Photos.Photo_ID && Photos.Event_ID = $eid");
I am new to these statements, any help or guidance is greatly appreciated.
Here's your query:
SELECT
Photos.Filename, Photos.Filetype
FROM Photos
INNER JOIN PhotoUserTags ON (PhotoUserTags.Photo_ID = Photos.Photo_ID)
WHERE
Photos.Event_ID = $eid
AND PhotoUserTags.User_ID IN ($friendlist) /* assuming they are IDs separated by a comma) */
GROUP BY Photos.Photo_ID;
I would also explain this query just in case you use the right indexes to maximize the performance of your query
For one, the logical and in mysql is not && but AND, like this:
SELECT * from table WHERE field1 = 'value1' AND field2 = 'value2';
You should also use the newer join syntax like this:
SELECT Photos.Filename, Photos.Filetype
FROM Photos, PhotoUserTags
INNER JOIN PhotoUserTags ON PhotoUserTags.Photo_ID = Photos.Photo_ID
WHERE PhotoUserTags.User_ID IN ($friendlist)
AND Photos.Event_ID = $eid
GROUP BY Photos.Photo_ID
Note the join expression (I used inner join, assuming a matching record needs to exist in both tables) - it makes your where cleaner and easier to read.
Does this help:
$result= mysql_query("SELECT Photos.Filename, Photos.Filetype
FROM Photos, PhotoUserTags
WHERE PhotoUserTags.User_ID IN ($friendlist) && PhotoUserTags.Photo_ID = Photos.Photo_ID && Photos.Event_ID = $eid GROUP BY Photos.Photo_ID");

Categories