问题
I have 2 tables, First table is user and second table is user_attendance.
In the user attendance I'm inserting IN and OUT per line, so 1 line for IN and 1 line for OUT.
I want a MySQL select(so I don't have to do it on Php) which will loop for every ID in users and get the last OUT and first IN of that user in user table.
I tried doing it on Php by selecting first all the ID in user and looping it Via php and Select the 1st in and Last out of that Id in attendance. Like so.
$userCreds = DB::table('users')->select('user_id', 'username')->get();
$emailBody = '<table border="1"><thead><tr><th>Employee ID</th><th>Employee Name</th><th>Date</th><th>IN</th><th>OUT</th></tr></thead><tbody>';
foreach ($userCreds as $userCred) {
$userAttendance = DB::select(
DB::raw(
"SELECT username,
(
SELECT TIME_FORMAT(time(b.server_time), '%r')
FROM `users` a
LEFT JOIN user_attendance b
ON a.user_id = b.user_id
WHERE a.user_id = $userCred->user_id
AND (b.server_time between '$ysDate' and '$yeDate')
AND b.action = 'IN' ORDER BY b.server_time ASC LIMIT 1
) as TimeIn,
(
SELECT TIME_FORMAT(time(b.server_time), '%r')
FROM `users` a
LEFT JOIN user_attendance b
ON a.user_id = b.user_id
WHERE a.user_id = $userCred->user_id
AND (b.server_time between '$ysDate' and '$yeDate')
AND b.action = 'OUT' ORDER BY b.server_time DESC LIMIT 1
) as TimeOut
FROM users
WHERE user_id = $userCred->user_id"
)
);
$emailBody .= '<tr><td>'.$userCred->user_id.'</td><td>'.$userCred->username.'</td><td>'.date('Y-m-d',(strtotime ( '-1 day' , strtotime ( $date) ) )).'</td><td>'.$userAttendance[0]->TimeIn.'</td><td>'.$userAttendance[0]->TimeOut.'</td></tr>';
}
Instead of doing it on Php, I want it to be done on the Mysql side so I can actually create a view which will be stored ever now and done for recording purposes.
What I need is like this
user table
user_id | username
01 | piglet
02 | pooh
03 | tiger
user_attendance table
user_id | servertime | action
01 | 2019-10-10 08:00:00 | IN
01 | 2019-10-10 09:00:00 | OUT
01 | 2019-10-10 10:00:00 | IN
01 | 2019-10-10 18:00:00 | OUT
02 | 2019-10-10 07:45:00 | IN
02 | 2019-10-10 09:00:00 | OUT
02 | 2019-10-10 10:00:00 | IN
02 | 2019-10-10 19:50:00 | OUT
Result will be
user_id | date | IN | OUT
01 | 2019-20-10 | 08:00:00 | 18:00:00
02 | 2019-20-10 | 07:45:00 | 19:50:00
回答1:
Here's the refactored sql
query.
first is to get your users table
second is the join the IN
time
third is to join the OUT
time
fourth is get the max()
and min()
time of user id then group by a.user_id.
SELECT a.user_id, TIME_FORMAT(time(min(b.server_time)), '%r') as TimeIn, TIME_FORMAT(time(max(c.server_time)), '%r') as TimeOut
FROM `users` a
LEFT JOIN user_attendance b ON a.user_id = b.user_id and (b.server_time between '$ysDate' and '$yeDate') and b.action = 'IN'
LEFT JOIN user_attendance c ON a.user_id = c.user_id and (c.server_time between '$ysDate' and '$yeDate') and c.action = 'OUT'
GROUP BY a.user_id
来源:https://stackoverflow.com/questions/58496561/mysql-foreach-from-one-table-to-another