Reputation: 45
I have a question - I have 2 tables like this :
tblattLogs:
| user_id | attendantLogs |
+---------+------------------+
| 01 | 2017-10-31 08:00 |
| 01 | 2017-10-31 12:00 |
| 01 | 2017-10-31 17:05 |
| 01 | 2017-10-31 17:10 |
| 02 | 2017-10-31 08:10 |
| 02 | 2017-10-31 11:00 |
| 02 | 2017-10-31 17:01 |
| 02 | 2017-10-31 17:05 |
......
tblusers:
| id | name | otherstuff |..
+----+------+------------+
| 01 | Joe | otherstuff |
| 02 | Jean | otherstuff |
...
and I want the following as a result:
| id | name | date | CheckIn | CheckOut |
+----+------+------------+---------+----------+
| 01 | Joe | 2017-10-31 | 08:00 | 17:10 |
| 02 | Jean | 2017-10-31 | 08:10 | 17:05 |
...
And my query looks like:
SELECT DISTINCT
t.[user_id],
MIN(t.attendantLogs) OVER (PARTITION BY [user_id]) AS CheckIn,
MAX(t.attendantLogs) OVER (PARTITION BY [user_id]) AS CheckOut,
n.name AS NAME
FROM
tblattLogs t, tblusers as n
WHERE
t.user_id = n.id
My question is: how do I create a query that shows me correct result as I want?
and I know my query is wrong. I'm literally beginner in SQL
. So, please correct me if I am wrong, and please help me to resolve this.
Upvotes: 3
Views: 992
Reputation: 28930
One way would be to use group by.DEMO based on data by Stuart
;with cte
as
(
select user_id,
cast(attendant_logs as date) as dt,
min(cast(attendant_logs as time)) as checkin,
max(cast(attendant_logs as time)) as checkout
from
#tblattLogs
group by user_id,
cast(attendant_logs as date)
)
select u.id,u.name,
c.*
from
#tblusers u
join
cte c
on c.user_id=u.id
Upvotes: 1
Reputation: 50173
Here is single SQL
Query which could help u to achieve the above result :
SELECT U.ID,
U.name,
CONVERT(DATE, MIN(L.attendantLogs)) [Date],
CONVERT(VARCHAR(8), MIN(L.attendantLogs), 108) [CheckIn],
CONVERT(VARCHAR(8), MAX(L.attendantLogs), 108) [CheckOut]
FROM tblattLogs L
INNER JOIN tblusers U ON U.id = L.USER_ID
GROUP BY U.id,
U.name;
Result :
ID name Date CheckIn CheckOut
01 Joe 2017-10-31 08:00:00 17:10:00
02 Jean 2017-10-31 08:10:00 17:05:00
Upvotes: 0
Reputation: 107347
The trick here is to build up a definitive list of all dates as a derived table or cte.
You can then CROSS JOIN
the users and dates tables, and then JOIN back to the Attendance data, grouping and using the MIN / MAX aggregates as before.
The LEFT JOIN
ensures that there will always be a record for every employee for any day on at least one employee went to work. The attendance will be NULL if that employee didn't check in / out at all.
WITH cteUniqueDates AS
(
SELECT DISTINCT CAST(attendantLogs AS DATE) as AttendanceDate
FROM tblattLogs
)
SELECT u.id, u.name, d.AttendanceDate, min(attendantLogs) AS CheckIn,
max(attendantLogs) AS CheckOut
FROM tblusers u
CROSS JOIN cteUniqueDates d
LEFT OUTER JOIN tblattLogs t
ON u.Id = t.user_id AND CAST(attendantLogs AS DATE) = d.AttendanceDate
GROUP BY u.id, u.name, d.AttendanceDate
ORDER BY d.AttendenceDate, u.id;
One caveat - this will only work if the employees check in and checkout on the same day. If the employees work overnight, things become more complicated.
Upvotes: 1