This is a sample output of my table(time_entries)
user_name| entry_type | entry_datetime
User1 | Time In | 28-JUL-13 16:40:40
User1 | Time Out | 28-JUL-13 16:40:41
User2 | Time In | 28-JUL-13 16:41:13
User2 | Time Out | 28-JUL-13 16:41:15
User1 | Time In | 27-JUL-13 16:42:30
User1 | Time Out | 27-JUL-13 16:42:34
User2 | Time In | 27-JUL-13 16:43:32
User2 | Time Out | 27-JUL-13 16:43:35
Now I used this query
SELECT te.user_name, te.entry_name, MAX(te.entry_datetime) AS date
FROM time_entries AS te
GROUP BY te.entry_type, te.user_name
and the result is this
user_name| entry_type | entry_datetime
User1 | Time In | 28-JUL-13 16:40:40
User1 | Time Out | 28-JUL-13 16:40:41
User2 | Time In | 28-JUL-13 16:41:13
User2 | Time Out | 28-JUL-13 16:41:15
QUESTION: Is there a way to merge username with the same name in 1 line? and have an output something like this.
user_name| Date | Timein | Timeout
User1 | 28-JUL-13 | 16:40:40 | 16:40:41
User2 | 28-JUL-13 | 16:41:13 | 16:41:15
I'm a little confuse how to do it.
I would approach it in this manner:
The end result:
SELECT te.user_name, LEFT(te.entry_datetime, 10) AS entry_date, cin.entry_datetime AS timein, cout.entry_datetime AS timeout
FROM time_entries te
LEFT JOIN (SELECT user_name, LEFT(entry_datetime, 10) AS entry_date, MIN(entry_datetime) AS entry_datetime
FROM time_entries
WHERE entry_type = 'Time In'
GROUP BY user_name, entry_date
) cin ON cin.user_name = te.user_name AND cin.entry_date = LEFT(te.entry_datetime, 9)
LEFT JOIN (SELECT user_name, LEFT(entry_datetime, 10) AS entry_date, MAX(entry_datetime) AS entry_datetime
FROM time_entries
WHERE entry_type = 'Time Out'
GROUP BY user_name, entry_date
) cout ON cout.user_name = te.user_name AND cout.entry_date = LEFT(te.entry_datetime, 10)
GROUP BY te.user_name, entry_date;
Btw, I'm using LEFT()
here because your column doesn't contain an actual date format that MySQL understands.
What about this?
select
user_name,
date(entry_datetime) as date,
min(entry_datetime) as Timein,
max(entry_datetime) as Timeout
from (
SELECT te.user_name, te.entry_name, MAX(te.entry_datetime) AS date
FROM time_entries AS te
GROUP BY te.entry_type, te.user_name) src
group by user_name, date
Here is a php side solution on how you can process the data.
function transformArray($data) {
$final = array();
foreach ($data as $key => $row) {
if (!isset($final[$row['u']])) $final[$row['u']] = array('user' => $row['u']);
$final[$row['u']][$row['t']] = date("H:i:s", strtotime($row['entrydatetime']));
$final[$row['u']]['date'] = date("d:M:y", strtotime($row['entrydatetime']));
}
return $final;
}
You can pass it a data set that looks like this, you can adjust the field names as nessecery.
$data = array(
array('u' => 'user1', 't' => 'TimeIn', 'entrydatetime' => '28-JUL-13 16:40:40'),
array('u' => 'user1', 't' => 'TimeOut', 'entrydatetime' => '28-JUL-13 16:40:40'),
array('u' => 'user2', 't' => 'TimeIn', 'entrydatetime' => '28-JUL-13 16:40:40'),
array('u' => 'user2', 't' => 'TimeOut', 'entrydatetime' => '28-JUL-13 16:40:40')
);
This will do the job:
SELECT te.user_name,DATE(te.entry_datetime) as Date,te.entry_datetime AS TimeIn,te2.entry_datetime AS TimeOut
FROM time_entries te
JOIN time_entries te2 ON te.user_name=te2.user_name AND te2.entry_type="Time Out" AND
te2.entry_datetime=
(
SELECT
entry_datetime
FROM
time_entries
WHERE entry_type='Time Out' AND user_name=te.user_name AND entry_datetime > te.entry_datetime
ORDER BY
ABS(TIMESTAMPDIFF(SECOND, te.entry_datetime, `entry_datetime`))
LIMIT 1
)
WHERE te.entry_type="Time In";
Edit: a little explanation:
It selects the user_name, the date part and the entry_datetime for the TimeIn part. Then it joins on the same table to fetch the Time Out datetime part. It does this by selecting the entry with type "Time Out" with the same user_name and the date that is closest to the Time In datetime.
select
user_name,
dATE(entry_datetime) AS date1,
min(entry_datetime) as Timein,
max(entry_datetime) as Timeout
from time_entries
group by user_name, date1
This Query will work appropriately when for every Time_In there is corresponding timeout. and each and every new day entry type should start with time_in