Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

select punctuality report with sql

I Have 3 tables.

1.tblAccess

+------------+--------------+----------+-----------------+------------+-------+
| EmployeeId | EmployeeName | Location |   AccessTime    | ReaderType |Branch |
+------------+--------------+----------+-----------------+------------+-------+
| _1346      | A            | L1       | 7/11/2014 10:00 | IN         |NBAD001|
| _1347      | B            | L2       | 7/10/2014 10:58 | IN         |NBAD001|
| _1346      | A            | L3       | 7/11/2014 23:39 | OUT        |NBAD001|
| _1347      | B            | L4       | 7/10/2014 23:58 | OUT        |NBAD001|
| _1364      | C            | L5       | 7/11/2014 10:00 | IN         |NBAD005|
| _1367      | D            | L6       | 7/10/2014 10:58 | IN         |NBAD002|
| _1367      | D            | L7       | 7/10/2014 22:42 | OUT        |NBAD002|
| _1364      | C            | L8       | 7/11/2014 23:58 | OUT        |NBAD005|
| _1422      | E            | L9       | 7/11/2014 23:58 | IN         |NBAD004|
| _1422      | E            | L10      | 7/11/2014 23:10 | IN         |NBAD004|
| _1111      | F            | L20      | 7/10/2014 23:10 | OUT        |NBAD003|
+------------+--------------+----------+-----------------+------------+-------+

2.tblBranch

+---------------+----------+-------------------+
| BranchEntryId | BranchID |    BranchName     |
+---------------+----------+-------------------+
|            24 | NBAD001  | Motor City Branch |
|            25 | NBAD002  | B2                |
|            26 | NBAD003  | B3                |
|            27 | NBAD004  | B4                |
|            28 | NBAD005  | B5                |
|            29 | NBAD006  | B6                |
|            30 | NBAD007  | B7                |
+---------------+----------+-------------------+

3.tblBranchTimingEntry

+-------------------+---------------+-----------+-----------+----------+-----------+----------+-----------+-----------+------------+-------------+--------------+------------+-------------+----------+-----------+------------+-------------+
| BranchTimeEntryID | BranchEntryID | fromDate  |  toDate   | SundayIn | SundayOut | MondayIn | MondayOut | TuesdayIn | TuesdayOut | WednesdayIn | WednesdayOut | ThursdayIn | ThursdayOut | FridayIn | FridayOut | SaturdayIn | SaturdayOut |
+-------------------+---------------+-----------+-----------+----------+-----------+----------+-----------+-----------+------------+-------------+--------------+------------+-------------+----------+-----------+------------+-------------+
|                 1 |            24 | 7/10/2014 | 7/30/2014 | 0:00     | 0:00      | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 9:30     | 15:30     | 9:30       | 15:30       |
|                 2 |            24 | 7/1/2014  | 7/9/2014  | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
|                 3 |            25 | 7/1/2014  | 7/30/2014 | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
|                 4 |            26 | 7/1/2014  | 7/30/2014 | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
|                 5 |            27 | 7/1/2014  | 7/30/2014 | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
|                 6 |            28 | 7/1/2014  | 7/30/2014 | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
|                 7 |            29 | 7/1/2014  | 7/30/2014 | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
|                 8 |            30 | 7/1/2014  | 7/30/2014 | 10:00    | 18:00     | 10:00    | 18:00     | 10:00     | 18:00      | 10:00       | 18:00        | 10:00      | 18:00       | 0:00     | 0:00      | 0:00       | 0:00        |
+-------------------+---------------+-----------+-----------+----------+-----------+----------+-----------+-----------+------------+-------------+--------------+------------+-------------+----------+-----------+------------+-------------+

I want to create a punctuality report in which we show employee, branch, In Time, Schedule Time and emp is Late or Early or On Time.

  • There will be multiple IN for same day for employees.So need first IN.
  • need to get details day wise,between two dates, group by EmployeeId
  • Need to select the schedule time from tblBranchTimingEntry based on branch and the day of access. ie. if it is Sunday then take SundayIn, else if its Monday then MondayIn and so on.
  • Also there will be different time schedule for a branch with different date range. For eg: In a month for a branch the first 15 days they have one schedule and for the next 15 days another schedule.
  • So when we take report for a month, we have to select schedule time for which the accessDate is between the FromDate and ToDate from tblBranchTimingEntry
  • So for the first 15 days the Schedule time will take from the SundayIn or MondayIn or so on....which is between that date range and next 15 days from the next date range.

My Logic goes like this

  1. we select first IN time of employees in a day from tblAccess
  2. and according to branch, we select BranchEntryId from tblBranch
  3. and select the row from tblBranchTimingEntry matched with the BranchEntryId and AccessTime from tblAccess between fromDate and toDate from tblBranchTimingEntry.
  4. and select the column corresponding day of the week, ie. SundayIn for Sunday, and so on.
  5. Then we calculate the time variance, (ScheduleTime - InTime). and if the variance > 0 then late by that much variance. if it is equal to 0 then emp is on time. If it is < 0 , then emp is early from schedule.

Result needed

+-------------+-------------------+---------+-----------+---------+--------------+---------------------+
| Employee ID |       Name        | Branch  |   Date    | In Time | ScheduleTime |    TimeVariance     |
+-------------+-------------------+---------+-----------+---------+--------------+---------------------+
| _1487       | basement paking   | NBAD001 | 10/7/2014 | 23:01   | 10:00        | Late By 13:01 hours  |
| _1346       | CHARLEY BAOUAMINA | NBAD001 | 10/7/2014 | 23:05   | 10:00        | Late By 13:05 hours  |
| _1268       | DANA AZZI         | NBAD001 | 10/7/2014 | 23:51   | 10:00        | Late By 13:51 hours |
| _1585       | DANA AZZI         | NBAD003 | 10/7/2014 | 23:48   | 0:00         | Late By 23:48 hours |
+-------------+-------------------+---------+-----------+---------+--------------+---------------------+

What I done so far?

I have this query. (actually the query is modified from the answer of my previous question from here by @wewesthemenace)

    ;WITH CTE AS(
    SELECT
        EmployeeID,
        EmployeeName,
        [Branch],
        AccessDate = CAST(AccessTime AS DATE),
        AccessTime = CAST(AccessTime AS TIME),
        Location,
        ReaderType,
        In_RN = ROW_NUMBER() OVER(PARTITION BY EmployeeId, CAST(AccessTime AS DATE), ReaderType ORDER BY CAST(AccessTime AS TIME) ASC)
        --Out_RN = ROW_NUMBER() OVER(PARTITION BY EmployeeId, CAST(AccessTime AS DATE), ReaderType ORDER BY CAST(AccessTime AS TIME) DESC)
    FROM tblAccess
    where CAST(AccessTime AS DATE) between '2014-07-10' and '2014-07-11'
    AND ReaderType = 'IN'
)
SELECT
ROW_NUMBER() OVER (ORDER BY EmployeeID) AS [Sl No],
    EmployeeID as[Employee ID],
    EmployeeName as [Name],
    [Branch],
    [Date] = CONVERT(VARCHAR(10), AccessDate, 103),
    [In Time] = ISNULL(SUBSTRING(CONVERT(VARCHAR(20), MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END)), 1, 5), '')
    , ScheduleTime =
         CASE DATENAME(DW,AccessDate)
         WHEN 'Sunday' THEN (select TOP 1 (( SUBSTRING( convert(varchar, [SundayIn],108),1,5))) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
         WHEN 'Monday' THEN (select TOP 1 ((SUBSTRING( convert(varchar, [MondayIn],108),1,5) )) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
         WHEN 'Tuesday' THEN (select TOP 1 ((SUBSTRING( convert(varchar, [TuesdayIn],108),1,5))) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
         WHEN 'Wednesday' THEN (select TOP 1 ((SUBSTRING( convert(varchar, [WednesdayIn],108),1,5) )) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
         WHEN 'Thursday' THEN (select TOP 1 ((SUBSTRING( convert(varchar, [ThursdayIn],108),1,5))) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
         WHEN 'Friday' THEN (select TOP 1 ((SUBSTRING( convert(varchar, [FridayIn],108),1,5) )) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
         WHEN 'Saturday' THEN (select TOP 1 ((SUBSTRING( convert(varchar, [SaturdayIn],108),1,5) )) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))
           END
    , TimeVariance =
      CASE DATENAME(DW,AccessDate)
        WHEN 'Sunday' THEN 
            (select TOP 1( case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SundayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SundayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SundayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SundayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SundayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SundayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))

        WHEN 'Monday' THEN 
            (select TOP 1(case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[MondayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[MondayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[MondayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[MondayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[MondayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[MondayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))


        WHEN 'Tuesday' THEN 
            (select TOP 1(case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[TuesdayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[TuesdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[TuesdayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[TuesdayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[TuesdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[TuesdayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))


        WHEN 'Wednesday' THEN 
            (select TOP 1(case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[WednesdayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[WednesdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[WednesdayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[WednesdayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[WednesdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[WednesdayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))


        WHEN 'Thursday' THEN 
            (select TOP 1(case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[ThursdayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[ThursdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[ThursdayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[ThursdayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[ThursdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[ThursdayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))

        WHEN 'Friday' THEN 
            (select TOP 1(case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[FridayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[FridayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[FridayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[FridayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[FridayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[FridayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))

        WHEN 'Saturday' THEN 
            (select TOP 1(case 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SaturdayIn]) as float) < 0 then 'Late By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SaturdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SaturdayIn]))%3600/60 as varchar(10))+ ' hours' 
            when cast(DATEDIFF(s,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SaturdayIn]) as float) = 0 then 'On Time'
            else 'Early By '+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SaturdayIn]))/3600 as varchar(10))+ ':'+ cast(ABS(DATEDIFF(S,ISNULL(MAX(CASE WHEN ReaderType = 'IN' AND In_RN = 1 THEN AccessTime END), null),[SaturdayIn]))%3600/60 as varchar(10))+ ' hours' end) from [dbo].[tblBranchTimingEntry] where BranchEntryID= (select [BranchEntryId] from [dbo].[tblBranch] where [BranchID]= [Branch]))

      END
FROM CTE 
WHERE In_RN = 1
GROUP BY EmployeeID, EmployeeName, AccessDate, [Branch]
ORDER BY EmployeeName, AccessDate

Here I dont know how to compare the access date with from date and to date in from tblBranchTimingEntry. So I select the TOP 1 result in ScheduleTime and TimeVariance in query. else the subquery return multiple rows.

Is there any other way to do this? Or how can i get the records from tblBranchTimingEntry where the accessdate between fromdate and todate.

Thank You


EDIT

As there is no other better answers posted, I am answering this question myself.

like image 814
Sharon Avatar asked Nov 28 '25 13:11

Sharon


1 Answers

I think your query is too complicated. This should basically be a join on the three tables with some fancy logic.

This resulting query isn't that simple, because you need logic to:

  • get the first access for an employee each day
  • compare the actual datetime the employee enters with the expected time
  • do a lot of date arithmetic

However, this should not require additional subqueries. Something like this:

select a.EmployeeId, a.Branch, 
       (case when cast(cast(accesstime as date) as datetime) + sundayin) < accesstime
             then 'Late by '
             else 'Early by '
        end) +
       (cast (case when DATENAME(DW, AccessDate) = 'Sunday'
                   then datediff(second, accesstime,
                                 cast(cast(accesstime as date) as datetime) + sundayin)
                   when . . .
              end) as varchar(255)) + ' seconds'
from (select a.*,
             row_number() over (partition by employeeid, cast(accesstime as date) order by accesstime) as seqnum
      from tblAccess a
      where CAST(AccessTime AS DATE) between @DateFrom and @DateTo AND
            ReaderType = 'IN'
     ) a join
     tblBranch b
     on a.branch = b.branchid and a.seqnum = 1 join
     tblBranchTimingEntry bte
     on b.BranchTimeEntryID = bte.BranchTimeEntryID
like image 93
Gordon Linoff Avatar answered Dec 01 '25 10:12

Gordon Linoff