How can I optimize query to run faster (Query inside a Query) - php

This query will take around 5 seconds to complete. I mean when I refresh or navigate to the page it will take 5 seconds to complete the browser loading and to display the total counts.
Here is what I want to achieve, FIRST is to get the MAX value of the systemID (ID) based on the empID.
But before the First query ends I made another query the will get the row where the empID has a JUMP value on the eStatus col.
This is to compare the year difference of the latest data startDate of the empID and to his previous JUMP endDate.
Here is my table
---|-------|-----------|------------|---------
ID | empID | startDate | endDate | eStatus
---|-------|-----------|------------|---------
1 | 10 | 2001-1-31 | 2001-12-31 |
2 | 10 | 2002-1-31 | 2002-12-31 |
3 | 22 | 2001-1-31 | 2001-12-31 |
4 | 10 | 2003-1-31 | 2003-12-31 | JUMP
5 | 10 | 2004-1-31 | 2004-12-31 |
6 | 22 | 2002-1-31 | 2002-12-31 | JUMP
7 | 10 | 2005-1-31 | 2005-12-31 |
8 | 22 | 2003-1-31 | 2003-12-31 |
9 | 22 | 2004-1-31 | 2004-12-31 |
10 | 10 | 2006-1-31 | 2006-12-31 | JUMP
11 | 10 | 2007-1-31 | 2007-12-31 |
12 | 10 | 2008-1-31 | 2008-12-31 |
13 | 10 | 2009-1-31 | 2009-12-31 | JUMP
14 | 10 | 2010-1-31 | 2010-12-31 |
15 | 10 | 2011-1-31 | 2011-12-31 |
the First query will get the max ID by group of empID.
---|-------|-----------|------------|---------
ID | empID | startDate | endDate | eStatus
---|-------|-----------|------------|---------
15 | 10 | 2011-1-31 | 2011-12-31 |
9 | 22 | 2004-1-31 | 2004-12-31 |
the Second query will get the empID row that has a JUMP data on the eStatus Col
---|-------|-----------|------------|---------
ID | empID | startDate | endDate | eStatus
---|-------|-----------|------------|---------
4 | 10 | 2003-1-31 | 2003-12-31 | JUMP
6 | 22 | 2002-1-31 | 2002-12-31 | JUMP
10 | 10 | 2006-1-31 | 2006-12-31 | JUMP
13 | 10 | 2009-1-31 | 2009-12-31 | JUMP
6 | 22 | 2002-1-31 | 2002-12-31 | JUMP
Now I can compute the date difference from startDate of 1st query and enddate of 2nd query. If it is greater than 2 the it will count to my final count.
THANK YOU SO MUCH IN ADVANCE and KEEP SAFE.
Here is my code:
<?php
$counterA= 0;
$counterB= 0;
$finalCount = 0;
$result = mysqli_query($con,"SELECT empID,endDate FROM tablerecord
WHERE ID IN (SELECT MAX(ID) FROM tablerecord GROUP BY empID)");
while ($row=mysqli_fetch_assoc($result )) {
$counterA++; //count how many result based on the above query
$emp_max = $row['empID']; //Get emp ID based on max ID
endDate_result = $row['endDate']; //Get endDate based on max ID
$resultPrevious=mysqli_query($con,"SELECT empID,startDate FROM tablerecord
WHERE empID = '$emp_max' AND eStatus = 'JUMP' ");
while ($rowPrevious=mysqli_fetch_assoc($resultPrevious)) {
$counterB++; //count how many result based on the above query
$dateA=date_create($rowPrevious['startDate']);
$dateB=date_create($endDate_result);
$diff2=date_diff($dateA,$dateB);
$numLenght = $diff2->y;
if ($numLenght > 2) {
$finalCount++;
}
}
}
echo $counterA;
echo "<br>";
echo $counterB;
echo "<br>";
echo $finalCount;
?>

if I understand correctly, what you want is to select all data that have eStatus value jump.
why not simply SELECT empID,startDate FROM tablerecord WHERE empID IN(SELECT MAX(ID) FROM tablerecord) AND eStatus = 'JUMP'?
or, if you want the unique value of empID, SELECT empID,startDate FROM tablerecord WHERE empID IN(SELECT DISTINCT(ID) FROM tablerecord) AND eStatus = 'JUMP'
all my query above will not produce any result
you might want to try multiple select in your query for a crude way to get it all in one go
select * from tablerecord where empID in(SELECT empID FROM tablerecord WHERE ID IN (SELECT MAX(ID) FROM tablerecord group by empID)) and eStatus = 'JUMP'
in this way, you only query the DB one time and the rest can be done with your PHP code

I would use this query to get all needed data :
# Get first and last jump for each empID
SELECT *
FROM tablerecord t1
WHERE t1.ID = (
SELECT MIN(t2.ID)
FROM tablerecord t2
WHERE t1.empID==t2.empID
) or t1.ID = (
SELECT MAX(t3.ID)
FROM tablerecord t3
WHERE t1.empID==t3.empID
)
And then some PHP to run through, comparing each pairs
$result = mysqli_query($con,"the_previous_query....");
$row_to_compare_with =false;
while ($row=mysqli_fetch_assoc($result )) {
if ($row_to_compare_with == false) {
$row_to_compare_with = $row;
} else {
// Compare $row_to_compare_with with $row, both having same empId
// do your thing here...
$row_to_compare_with = false;
}
}

Related

Mysql select UNIQUE row on column

I have a table as following:(Ex)
id | vid | time
------------------------
1 | 4 | 1333635317
2 | 4 | 1333635323
3 | 2 | 1333635336
4 | 4 | 1333635343
5 | 5 | 1333635349
I want to be just a row (the last row [ID: 4]) of the same rows[id:1,2,4], how it will output the query?
I mean, as a result of these:
id | vid | time
------------------------
3 | 2 | 1333635336
4 | 4 | 1333635343
5 | 5 | 1333635349
What do i do?
i trying it as:
SELECT * from tbale as t1 where vid = 4 GROUP BY vid ORDER BY id DESC
but doesn't work ORDER BY in my query.
Get the max time per vid and use in to get those rows from the table.
select * from tablename
where (vid,time) in (select vid,max(time)
from tablename
group by vid)
order by id

PHP stack multiple values into one value

This is the bookings table I'm using for my query
+----------------------+
| event_id | person_id |
+----------------------+
| 5 | 7 |
| 4 | 7 |
| 3 | 7 |
| 4 | 5 |
| 3 | 5 |
| 5 | 3 |
+----------------------+
This table shows that person_id 7 has 3 bookings, 5 has 2 bookings and 3 has 6 bookings.
Currently, I'm using this query to get the total number of bookings per person.
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
bookings.event_id,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
$result = mysql_query($query);
if($result) {
while($row = mysql_fetch_array($result))
{
/* total bookings per user */
$value = $row['total'];
$sum += $value;
/* events booked per user */
$events....
/* Displaying results */
echo "<tr width='500'>";
echo "<td>".$row['person_id']."</td>";
echo "<td>".$row['display_name']."</td>";
echo "<td>".$row['total']."</td>";
echo "<td>".$events."</td>";
echo "</tr>";
}
This works okay and gives me:
+-----------------------------------+
| ID | NAME | Total Bookings |
+-----------------------------------+
| 7 | Bob | 3 |
| 5 | Jane | 2 |
| 3 | Joe | 1 |
+-----------------------------------+
I'm seeking help to get this to display the events booked by each person (like the 4th columns below):
+------------------------------------------------+
| ID | NAME | Total Bookings | Event IDs |
+------------------------------------------------+
| 7 | Bob | 3 | 5,4,3 |
| 5 | Jane | 2 | 4,3 |
| 3 | Joe | 1 | 5 |
+------------------------------------------------+
Could you please help me getting there.
Thanks.
GROUP_CONCAT https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
GROUP_CONCAT(bookings.event_id) as event_ids,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
A bit different query but same result:
SELECT
bookings.person_id,
COUNT(
bookings.person_id
) AS total,
users.display_name,
GROUP_CONCAT(
bookings.event_id
ORDER BY
bookings.event_id
) AS events_list
FROM
bookings,
users
WHERE
bookings.person_id=users.id
GROUP BY
bookings.person_id
ORDER BY
bookings.person_id
I don't know if for a large data, the execution time is less, more or equal.

Is it possible to sort by the duration of time when its computed based on the joined table?

I have a query to get the total number of duration of when the user become internal,hm,rec status. I wanted to ask, is it possible to sort it by total number of duration when it's re calculated from another table? Please see my query structure to understand further.
The user can be assigned into many status. It can be that he was in internal status for 4th times,rc for 2 times and etc.
$sql = "SELECT * FROM user WHERE creation_date < NOW()";
$qry = mysql_query($sql);
$res = array();
while($row=mysql_fetch_assoc($qry))
{
$res[] = $row;
$res['duration'] = getTimeDuration($row['userId'],$row['startDate']);
}
function getTimeDuration($userId,$startDate);
{
$sql = "SELECT statusDate FROM userStatus WHERE userId=$userId AND status IN('internal','hm','rec') ORDER BY statusDate DESC
$qry = mysql_query($sql);
While($row=mysql_fetch_assoc($qry))
{
$diff = $row['statusDate']-$startDate;
$duration = $duration + $diff;
}
return $duration;
}
This is the table structure
user Table
+----------+--------------+
| userId | startDate |
+----------+--------------+
| 1 | 2011-09-18 |
+----------+--------------+
| 2 | 2012-05-25 |
+----------+--------------+
userStatus Table
+----------+--------------+--------------+
| userId | statusDate | status |
+----------+--------------+--------------+
| 1 | 2012-09-18 | internal |
+----------+--------------+--------------+
| 1 | 2012-10-18 | hm |
+----------+--------------+--------------+
| 1 | 2012-10-25 | rec |
+----------+--------------+--------------+
| 1 | 2012-11-05 | manager |
+----------+--------------+--------------+
| 1 | 2012-11-15 | assistant |
+----------+--------------+--------------+
| 1 | 2012-12-05 | internal |
+----------+--------------+--------------+
| 2 | 2012-10-05 | rec |
+----------+--------------+--------------+
| 2 | 2012-11-05 | internal |
+----------+--------------+--------------+
Output:
http://screencast.com/t/BsgouWSc5H3m
In my screenshot, USER ID: 1 had a total time duration all in all for 1589. USER ID: 2 has a duration of 297. What I want is to add the ability to sort base on the total time of duration. In this case, if DESC USER ID 1 will show first. Then, if ASC USER ID: 2 will show first.

how use order by clause in group by statement

I have two table tbl_issue_log, tbl_magazine_issue
tbl_issue_log
============
+----------+--------+--------+-----------+---------------------+
| issue_id | mag_id | log_id | operation | updated_time |
+----------+--------+--------+-----------+---------------------+
| 2 | 1 | 1 | 1 | 2014-01-30 21:29:44 |
| 3 | 4 | 1 | 1 | 2015-01-30 21:29:44 |
| 2 | 1 | 1 | 3 | 2015-01-31 21:29:44 |
+----------+--------+--------+-----------+---------------------+
tbl_magazine_issue
=================
+----------+-------------+-------------+------------------+------------+------------+-------------------+---------------+
| ISSUE_ID | ISSUE_NAME | MAGAZINE_ID | COVER_PAGE_THUMB | FROM_DATE | TO_DATE | issue_description | login_page_no |
+----------+-------------+-------------+------------------+------------+------------+-------------------+---------------+
| 2 | test issue | 1 | cover page | 2014-01-30 | 2015-01-30 | sdssdg fsdf | 20 |
| 3 | test issue1 | 4 | cover page1 | 2014-01-30 | 2015-01-30 | sdssdg fsdf | 20 |
+----------+-------------+-------------+------------------+------------+------------+-------------------+---------------+
in tbl_issue_log contain multiple records for same issue id. i want only one issue at a time
and this must latest updated time.
My query is this
SELECT
`tbl_issue_log`.`operation`,
`tbl_magazine_issue`.`ISSUE_ID`,
`tbl_magazine_issue`.`ISSUE_NAME`,
`tbl_magazine_issue`.`MAGAZINE_ID`,
`tbl_magazine_issue`.`COVER_PAGE_THUMB`,
`tbl_magazine_issue`.`FROM_DATE`,
`tbl_magazine_issue`.`TO_DATE`,
`tbl_magazine_issue`.`issue_description`,
`tbl_magazine_issue`.`login_page_no`
FROM
`tbl_issue_log`
LEFT JOIN
`tbl_magazine_issue` ON tbl_magazine_issue.ISSUE_ID = tbl_issue_log.issue_id
WHERE
(tbl_issue_log.mag_id = '1')
AND (tbl_magazine_issue.ISSUE_STATUS = 3)
AND (tbl_issue_log.updated_time > '2014-02-25 00:42:22')
GROUP BY tbl_issue_log.issue_id
ORDER BY tbl_issue_log updated_time DESC;
Here i got issue id based output . But not getting the latest updated timeed record.
If any one about this please help me.
Try this
SELECT * FROM
(SELECT
`tbl_issue_log`.`operation`,
`tbl_magazine_issue`.`ISSUE_ID`,
`tbl_magazine_issue`.`ISSUE_NAME`,
`tbl_magazine_issue`.`MAGAZINE_ID`,
`tbl_magazine_issue`.`COVER_PAGE_THUMB`,
`tbl_magazine_issue`.`FROM_DATE`,
`tbl_magazine_issue`.`TO_DATE`,
`tbl_magazine_issue`.`issue_description`,
`tbl_magazine_issue`.`login_page_no`
FROM
`tbl_issue_log`
LEFT JOIN
`tbl_magazine_issue` ON tbl_magazine_issue.ISSUE_ID = tbl_issue_log.issue_id
WHERE
(tbl_issue_log.mag_id = '1')
AND (tbl_magazine_issue.ISSUE_STATUS = 3)
AND (tbl_issue_log.updated_time > '2014-02-25 00:42:22')
ORDER BY tbl_issue_log.updated_time DESC ) TEMP_TABLE
GROUP BY ISSUE_ID
Can you try changing order by clause as
ORDER BY tbl_issue_log.updated_time DESC;
Edit ---
As you are grouping on issue_id, mysql will select first row that matches the issue_id. The order by runs later which essentially does not return what you are looking for. You may need to use a subquery approach for this.
select some_table.* FROM
(
SELECT
MAX(tbl_issue_log.updated_time) AS updated_time,
`tbl_issue_log`.`operation`,
`tbl_magazine_issue`.`ISSUE_ID`,
`tbl_magazine_issue`.`ISSUE_NAME`,
`tbl_magazine_issue`.`MAGAZINE_ID`,
`tbl_magazine_issue`.`COVER_PAGE_THUMB`,
`tbl_magazine_issue`.`FROM_DATE`,
`tbl_magazine_issue`.`TO_DATE`,
`tbl_magazine_issue`.`issue_description`,
`tbl_magazine_issue`.`login_page_no`
FROM
`tbl_issue_log`
LEFT JOIN
`tbl_magazine_issue` ON tbl_magazine_issue.ISSUE_ID = tbl_issue_log.issue_id
WHERE
(tbl_issue_log.mag_id = '1')
AND (tbl_magazine_issue.ISSUE_STATUS = 3)
AND (tbl_issue_log.updated_time > '2014-02-25 00:42:22')
GROUP BY tbl_issue_log.issue_id
) some_table
ORDER BY some_table.updated_time DESC;

Count data in same sentence

I have table :
==========================================================
|id | before | after | freq | id_sentence | document_id |
==========================================================
| 1 | a | b | 1 | 0 | 1 |
| 2 | c | d | 1 | 1 | 1 |
| 3 | e | f | 1 | 1 | 1 |
| 4 | g | h | 2 | 0 | 2 |
==========================================================
I want to get the number of data depend on the id_sentence and freq so the result must be 1 2 1
here's the code :
$query = mysql_query("SELECT freq FROM tb where document_id='$doc_id' ");
while ($row = mysql_fetch_array($query)) {
$stem_freq = $row['freq'];
$total = $total+$stem_freq;
but the result is still wrong. please, help me.. thank you :)
If I understand your question, you are trying the calculate the sum of freq for each distinct id_sentence for a particular document_id.
Try the following SQL:
SELECT id_sentence, SUM(freq) as freq FROM tb WHERE document_id = 1 GROUP BY(id_sentence)
The result will be rows of data with the id_sentence and corresponding total freq. No need to manually sum things up afterwards.
See this SQL Fiddle: http://sqlfiddle.com/#!2/691ed/8
I think you could do something like
SELECT count(*) AS count FROM tb GROUP BY(id_sentence,freq)
to do the counting you want. You could even do something like
SELECT count(*) AS count, id_sentence, freq FROM tb GROUP BY(id_sentence,freq)
to know which id_sentence,freq combination the count is for.

Categories