Mysql Grab last update by user id within a specified timeframe - php

I have two tables tc_users and tc_timeclock. I want to grab the current status of each active user. But only those that have made an update (clocked in or out) within the last 12 hours. I have gotten as far as figuring out how to grab all of the updates within the last 12 hours but not how to narrow it down to just the last one for each user.
Here are my tables:
tc_users:
user_id | first_name | last_name | active
-----------------------------------------
1 | Frank | Zappa | 1
2 | John | Mcneely | 1
3 | Bill | Mckenna | 1
4 | Mark | langdon | 1
5 | Steve | Mcalister | 0
6 | William | Stevens | 1
7 | John | Jones | 0
tc_timeclock:
tc_id | user_id | status | time_stamp
-------------------------------------
1 | 1 | IN | 2012-11-28 09:00:25
2 | 2 | IN | 2012-11-28 09:01:25
3 | 3 | IN | 2012-11-26 09:03:25
4 | 4 | IN | 2012-11-28 09:21:25
5 | 5 | IN | 2012-11-28 09:01:12
6 | 6 | IN | 2012-11-28 09:47:13
7 | 7 | IN | 2012-11-12 09:00:22
8 | 7 | OUT | 2012-11-12 09:03:28
9 | 5 | OUT | 2012-11-28 09:21:25
10 | 6 | OUT | 2012-11-28 11:47:13
11 | 3 | OUT | 2012-11-26 11:03:25
12 | 2 | OUT | 2012-11-28 11:01:25
13 | 1 | OUT | 2012-11-28 11:27:25
14 | 4 | OUT | 2012-11-28 11:21:25
15 | 4 | IN | 2012-11-28 12:21:25
16 | 1 | IN | 2012-11-28 12:27:25
17 | 3 | IN | 2012-11-26 12:03:25
18 | 6 | IN | 2012-11-28 12:47:13
19 | 2 | IN | 2012-11-28 12:01:25
20 | 1 | OUT | 2012-11-28 17:27:25
21 | 4 | OUT | 2012-11-28 17:21:25
22 | 3 | OUT | 2012-11-26 17:03:25
23 | 2 | OUT | 2012-11-28 17:01:25
So far This is the query I have come up with :
if now = 2012-11-28 18:00:00
SELECT first_name, last_name, status, time_stamp
FROM tc_timeclock
INNER JOIN tc_users
ON tc_timeclock.user_id = tc_users.user_id
WHERE tc_users.active = 1
AND tc_timeclock.time_stamp BETWEEN '2012-11-28 06:00:00' AND '2012-11-28 18:00:00'
This displays everything within the last 12 hours like so:
first_name | last_name | status | time_stamp
-----------------------------------------------------
Frank | Zappa | IN | 2012-11-28 09:00:25
John | Mcneely | IN | 2012-11-28 09:01:25
Mark | langdon | IN | 2012-11-28 09:21:25
William | Stevens | IN | 2012-11-28 09:47:13
William | Stevens | OUT | 2012-11-28 11:47:13
John | Mcneely | OUT | 2012-11-28 11:01:25
Frank | Zappa | OUT | 2012-11-28 11:27:25
Mark | langdon | OUT | 2012-11-28 11:21:25
Mark | langdon | IN | 2012-11-28 12:21:25
Frank | Zappa | IN | 2012-11-28 12:27:25
William | Stevens | IN | 2012-11-28 12:47:13
John | Mcneely | IN | 2012-11-28 12:01:25
Frank | Zappa | OUT | 2012-11-28 17:27:25
Mark | langdon | OUT | 2012-11-28 17:21:25
John | Mcneely | OUT | 2012-11-28 17:01:25
The logic I am looking for:
Grab the first and last name, current status and time the status was logged for each active user within the last 12 hours.
So output should be:
first_name | last_name | status | time_stamp
Frank | Zappa | OUT | 2012-11-28 17:27:25
John | Mcneely | OUT | 2012-11-28 17:01:25
Mark | langdon | OUT | 2012-11-28 17:21:25
William | Stevens | IN | 2012-11-28 12:47:13
User 5 (Steve Mcalister) and 7 (John Jones) are not active so they are not displayed.
User 3 (Bill Mckenna)has no activity within the last 12 hours so he is also no diplayed.
Am I missing something really simple? (I am sure I am)
I have a work around if there is not a simple solution, I could always add two columns to the tc_users table: (tc_users.current_status, and tc_users.status_time) and simply make those the same as the last entry into the tc_timeclock table.
That way I could easily select them, I don't like the idea of making the data redundant though if I don't have to.

Something like this might work for you.
SQL:
SELECT `tc_users`.`first_name`, `tc_users`.`last_name`, `tc_timeclock`.`status`, `temp_table`.`last_updated`
FROM `tc_users`
INNER JOIN `tc_timeclock`
ON `tc_users`.`user_id`=`tc_timeclock`.`user_id`
INNER JOIN (
SELECT `user_id`, MAX(`time_stamp`) AS `last_updated` FROM `tc_timeclock` GROUP BY `user_id`
) AS `temp_table`
ON `tc_users`.`user_id`=`temp_table`.`user_id`
AND `tc_timeclock`.`time_stamp`=`temp_table`.`last_updated`
WHERE `tc_users`.`active`!=0
AND `temp_table`.`last_updated`>(NOW() - INTERVAL 12 HOUR);
OUT:
+------------+-----------+--------+---------------------+
| first_name | last_name | status | last_updated |
+------------+-----------+--------+---------------------+
| William | Stevens | IN | 2012-11-28 12:47:13 |
| Frank | Zappa | OUT | 2012-11-28 17:27:25 |
| Mark | langdon | OUT | 2012-11-28 17:21:25 |
| John | Mcneely | OUT | 2012-11-28 17:01:25 |
+------------+-----------+--------+---------------------+
HTH

Query:
SQLFIDDLEExample
SELECT first_name, last_name, tml.status, tml.time_stamp
FROM (SELECT *
FROM tc_timeclock tl
WHERE tl.time_stamp = (SELECT MAX(time_stamp)
FROM tc_timeclock
WHERE tl.user_id = user_id )) tml
INNER JOIN tc_users
ON tml.user_id = tc_users.user_id
WHERE tc_users.active = 1
AND tml.time_stamp BETWEEN '2012-11-28 06:00:00' AND '2012-11-28 18:00:00'
Result:
| FIRST_NAME | LAST_NAME | STATUS | TIME_STAMP |
---------------------------------------------------------------------
| Frank | Zappa | OUT | November, 28 2012 17:27:25+0000 |
| John | Mcneely | OUT | November, 28 2012 17:01:25+0000 |
| Mark | langdon | OUT | November, 28 2012 17:21:25+0000 |
| William | Stevens | IN | November, 28 2012 12:47:13+0000 |

Related

How to select mysql results?

invoice
+----+-----+---------+-------+
| Sr | BRN | Name | Amnt |
+----+-----+---------+-------+
| 1 | 1 | John | 10 |
| 2 | 1 | John | 4 |
| 3 | 2 | Belly | 4 |
| 4 | 3 | John | 14 |
| 5 | 4 | John | 5 |
| 6 | 4 | John | 14 |
+----+-----+---------+-------+
I want to select all rows except the duplicate BRN. (If there are two/more ge in BRN then it should only select one)
I tried:
SELECT *(DISTINCT BRN) FROM invoice
Expected result:
+-----+---------+-------+
| BRN | Name | Amnt |
+-----+---------+-------+
| 1 | John | 10 |
| 2 | Belly | 4 |
| 3 | John | 14 |
| 4 | John | 5 |
+-----+---------+-------+
Given the following table:
+----+-----+---------+-------+
| Sr | BRN | Name | Amnt |
+----+-----+---------+-------+
| 1 | 1 | John | 10 |
| 2 | 1 | John | 4 |
| 3 | 2 | Belly | 4 |
| 4 | 3 | John | 14 |
| 5 | 4 | John | 5 |
| 6 | 4 | John | 14 |
+----+-----+---------+-------+
with the expected results:
+-----+---------+-------+
| BRN | Name | Amnt |
+-----+---------+-------+
| 1 | John | 10 |
| 2 | Belly | 4 |
| 3 | John | 14 |
| 4 | John | 5 |
+-----+---------+-------+
The difficult part is getting the amount, because it is arbitrary, not to mention that the values in Amnt are pretty much worthless in this result.
If you want distinct BRN, the query would be SELECT DISTINCT BRN FROM invoice
You might even get away with SELECT DISTINCT BRN, Name FROM invoice
An intermediate step would be SELECT BRN,Name FROM invoice GROUP BY BRN, Name
But if you try to include Amnt in the equation, then the query will fail because there's no way for the database to determine which Amnt to show.
So, you could try this kludge:
SELECT a.BRN, a.Name, b.Amnt FROM invoice AS a LEFT JOIN invoice AS b ON a.BRN=b.BRN
No guarantees on which Amnt it will pick up, though.
Hope that helps.
SELECT * FROM invoice WHERE Date >= :fdate GROUP BY BRN
See Here Use GROUP BY in Query with your Conditions

time slot for students and teacher

I am looking to set start time for first 20 students of a particular subject
at 9:00 AM and end time 10:00 AM, for the next 20 i want the time for the same subject 10:00 AM- 11 AM , this should happen for each subject, also i want that only 1 teacher for that particular subject should be alloted for each time slot,
i have tried a lot but still unable to come up with the solution.
user_table
user_id | user_name | contact_no | password | flag
6 | Abhis | 123456788 | 123 | s
5 | Abhish | 123456789 | 123 | s
8 | Sneha | 1111111111 | 123 | s
7 | Snehil | 1111112222 | 123 | s
1 | Narsingh | 1234567890 | 123 | t
2 | Abhinav | 1234567891 | 1234 | t
3 | Abhi | 1234567892 | 123 | s
4 | Abhishek | 1234567893 | 123 | s
subject_table
sub_id | sub_name
3 | CSS
1 | HTML
2 | JQUERY
enr_id | sub_id | user_id | date |
1 | 1 | 1 | 2016-04-01 |
2 | 2 | 1 | 2016-04-01 |
3 | 3 | 1 | 2016-04-01 |
4 | 1 | 5 | 2016-04-01 |
5 | 1 | 6 | 2016-04-01 |
6 | 1 | 7 | 2016-04-01 |
7 | 1 | 2 | 2016-04-01 |
8 | 2 | 2 | 2016-04-01 |

count of teachers and students for each subject

I have 3 tables, user_table to classify as a teacher or student, subject_table to mention different subject, and enrolled_table stating who registered as teacher/student and for which subject.
I want to have count of student, teacher count for each subject!
user_table
user_id | user_name | contact_no | password | flag
6 | Abhis | 123456788 | 123 | s
5 | Abhish | 123456789 | 123 | s
8 | Sneha | 1111111111 | 123 | s
7 | Snehil | 1111112222 | 123 | s
1 | Narsingh | 1234567890 | 123 | t
2 | Abhinav | 1234567891 | 1234 | t
3 | Abhi | 1234567892 | 123 | s
4 | Abhishek | 1234567893 | 123 | s
subject_table
sub_id | sub_name
3 | CSS
1 | HTML
2 | JQUERY
enrolled_table
enr_id | sub_id | user_id | date | start_time | end_time
1 | 1 | 1 | 2016-04-01 | 09:00:00 | 10:00:00
2 | 2 | 1 | 2016-04-01 | 10:00:00 | 11:00:00
3 | 3 | 1 | 2016-04-01 | 11:00:00 | 12:00:00
4 | 1 | 5 | 2016-04-01 | 09:00:00 | 10:00:00
5 | 1 | 6 | 2016-04-01 | 12:00:00 | 13:00:00
6 | 1 | 7 | 2016-04-01 | 12:00:00 | 13:00:00
7 | 1 | 2 | 2016-04-01 | 13:00:00 | 14:00:00
8 | 2 | 2 | 2016-04-01 | 13:00:00 | 14:00:00
SELECT
st.sub_name,
COUNT(CASE WHEN ut.flag = 's' THEN 1 END) AS students,
COUNT(CASE WHEN ut.flag = 't' THEN 1 END) AS teachers
FROM
subject_table st
INNER JOIN enrolled_table et ON et.sub_id = st.sub_id
INNER JOIN user_table ut ON ut.user_id = et.user_id
GROUP BY
st.sub_name

Dynamically create HTML table from sql query result

how can i write the sql query to get rows from multiple MySQL table and then output it to an HTML table as the format below.
I've been trying this for hours and I'm still not getting it.
Below is the HTML structure that I am trying to create
----------------------------------------------------------------
|student_id | full_name | TERM 1 | TERM2 | TERM 3 | TERM 4 |
----------------------------------------------------------------
| 1 | John Doe | 67 | 90 | NA | NA |
| 2 | John Smi | NA | NA | NA | NA |
| 3 | Doe John | 88 | 66 | NA | NA |
| 4 | Mike Doe | 57 | 78 | NA | NA |
| 5 | Doe Mike | NA | NA | NA | NA |
| 6 | Sam Doe | NA | NA | NA | NA |
----------------------------------------------------------------
And Here are the structures for the MySQL tables
--------------------------
| student_id | full_name |
--------------------------
| 1 | John Doe |
| 2 | John Smi |
| 3 | Doe John |
| 4 | Mike Doe |
| 5 | Doe Mike |
| 6 | Sam Doe |
--------------------------
------------------------
| exam_id | exam_name |
------------------------
| 11 | TERM 1 |
| 12 | TERM 2 |
| 13 | TERM 3 |
| 14 | TERM 4 |
------------------------
----------------------------------------
| subject_id | exam_id | subject_name |
----------------------------------------
| 1 | 11 | mathematics |
| 2 | 11 | english |
| 3 | 11 | physics |
| 4 | 12 | mathematics |
| 5 | 12 | english |
| 6 | 12 | physics |
----------------------------------------
---------------------------------------------
| subject_id | marks | student_id |
---------------------------------------------
| 1 | 67 | 1 |
| 2 | 54 | 4 |
| 3 | 88 | 3 |
| 4 | 90 | 1 |
| 5 | 78 | 4 |
| 6 | 66 | 3 |
---------------------------------------------
Thanks.
This is the query you want:
select s.student_id,
s.full_name,
avg(case when te.exam_name = 'TERM 1' then sm.marks else null end) as term_1,
avg(case when te.exam_name = 'TERM 2' then sm.marks else null end) as term_2,
avg(case when te.exam_name = 'TERM 3' then sm.marks else null end) as term_3,
avg(case when te.exam_name = 'TERM 4' then sm.marks else null end) as term_4
from students s
left join subject_marks sm
on s.student_id = sm.student_id
left join subject_exams se
on sm.subject_id = se.subject_id
left join term_exams te
on se.exam_id = te.exam_id
group by s.student_id,
s.full_name
Fiddle: http://sqlfiddle.com/#!2/fd1c82/1/0
As for outputting it to an HTML table, you want to look at a PHP/MySQL tutorial.

Mysql Timeclock status and hours updates

I have a table to record people clocking in and out. I need to find the best way to get a given person's records and add up their hours in a given time period
Here is the table:
tc_timeclock:
tc_id | user_id | status | time_stamp
-------------------------------------
1 | 1 | IN | 2012-11-28 09:00:25
2 | 2 | IN | 2012-11-28 09:01:25
3 | 3 | IN | 2012-11-26 09:03:25
4 | 4 | IN | 2012-11-28 09:21:25
5 | 5 | IN | 2012-11-28 09:01:12
6 | 6 | IN | 2012-11-28 09:47:13
7 | 7 | IN | 2012-11-12 09:00:22
8 | 7 | OUT | 2012-11-12 09:03:28
9 | 5 | OUT | 2012-11-28 09:21:25
10 | 6 | OUT | 2012-11-28 11:47:13
11 | 3 | OUT | 2012-11-26 11:03:25
12 | 2 | OUT | 2012-11-28 11:01:25
13 | 1 | OUT | 2012-11-28 11:27:25
14 | 4 | OUT | 2012-11-28 11:21:25
15 | 4 | IN | 2012-11-28 12:21:25
16 | 1 | IN | 2012-11-28 12:27:25
17 | 3 | IN | 2012-11-26 12:03:25
18 | 6 | IN | 2012-11-28 12:47:13
19 | 2 | IN | 2012-11-28 12:01:25
20 | 1 | OUT | 2012-11-28 17:27:25
21 | 4 | OUT | 2012-11-28 17:21:25
22 | 3 | OUT | 2012-11-26 17:03:25
23 | 2 | OUT | 2012-11-28 17:01:25
I of course can grab all of the rows for a user and it would include all of the IN and OUT status's.
I just don't know the best way to find the time difference (IE how long were they clocked in) between those statuses
The other issue which may be easy enough, is how to find all of this within a certain date range. (ie today, this business week, this pay period.)
Now I am thinking that a portion of this will need to be done in some php, just can't for the life of me figure out the logic.

Categories