6

I am doing a project called "Attendance Management System"

The company has its own biometric finger scanner who checks for employee's attendance and stored in on a database table.

The table consist of 4 fields (ID autonumber, EmployeeNo, CheckTime and CheckType)

The Timekeeping system store all the employee's logs and attendance but it doesn't specify whether the checktype is "I" or "O". As you can see the image below, everytime the employee log in, the system store it to database automatically but it stored as "I", and when the same employee log in again it will store as "I" again.

enter image description here

My client want it to be automated as possible. He wants to changed the checktype to "O" once the employee login again.

For example:

I am an employee. I am going to log in at today 8am, then it will store to database as

today 8AM with checktype "I".. since I am not aware that I have logged in already, I loged in again for the second time at 8:04 AM.. the system stores it as "I" again the same as if I am going to logout at 5PM, the system also record it as "I"..

I would like this to update the database automatically.Without any parameters provided by the user. I want it to be in a stored procedure to automate the process.

It should be restricted within the same employee: Example:

Employee1 logged at today 8am.. (checktype "I") Employee1 logged again at today 11am... (checktype "O") employee1 logged again at today 12pm.. (checktype "I") employee1 logged again at today 4pm (checktype "O")

Criterias should be restricted within employeeno, checktime only.. and would like to update checktype also based on given datas.

The old system is not capable storing logged ins as "O" it was purely "I"..

How to do this? I need your inputs and help badly! Please?

I have created a stored procedure but do not know where I can start it and I dont have the idea to finish the procedure and make it work..

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE AUTOMATIC_OVERRIDE
    @ID INT,
    @EMPLOYEENO NVARCHAR(20),
    @CHECKTIME DATETIME,
    @CHECKTYPE NVARCHAR(1)

AS
    SET NOCOUNT ON;
    WHILE @ID = (SELECT ID FROM CHECKTIME)

        SELECT ID,EMPLOYEENO,CHECKTIME,CHECKTYPE
          FROM CHECKTIME
         GROUP BY ID,EMPLOYEENO,CHECKTIME,CHECKTYPE
         ORDER BY CHECKTIME
GO

Please help me to solve this problem. Thanks.

WarrenT
  • 4,502
  • 19
  • 27
Dhenn
  • 295
  • 2
  • 7
  • 27
  • So basically what you want is to alternate the `In and Out` checkouts for a single employee, so it is possible to know when came in and when went out. – Yaroslav Aug 28 '12 at 07:28
  • yes... but I can't do it..can you help me? – Dhenn Aug 28 '12 at 07:29
  • T&A is a fairly complex process and is generally managed by having one or many shift patterns. These make it easier to map the times to the data coming from the clocking systems. What are the rules for processing the clock times? If you clock in at 0800 and 0804 which would be the actual start time? – u07ch Aug 28 '12 at 07:42
  • @u07ch , If I clock at 0800 it will be the start time onwards will be late.. – Dhenn Aug 29 '12 at 04:41
  • Check my answer, edited to added modified code and updated SQL Fiddle code to meet your date expectations. – Yaroslav Aug 30 '12 at 14:03
  • alright, thanks yaroslov i'll test it today. – Dhenn Aug 30 '12 at 23:52

3 Answers3

6

EDIT:

The solution into the PRC:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE AutomaticOverrideByID
    @ID INT,
    @EMPLOYEENO NVARCHAR(20)

AS

    UPDATE CHECKTIME
    SET CHECKTYPE = CASE WHEN (SELECT
    COUNT(ID) AS CountOfLogin
    FROM CHECKTIME
    WHERE CHECKTIME.EMPLOYEENO = @EMPLOYEENO 
    AND CHECKTIME.CheckTime < C.CheckTime) % 2 = 1 THEN 'O' ELSE CHECKTYPE END
    FROM CHECKTIME C
    WHERE C.ID = @ID

GO

And here is an UPDATE to the existing dataset as Dhenn asked:

UPDATE CHECKTIME
SET CHECKTYPE = CASE WHEN (SELECT
COUNT(ID) AS CountOfLogin
FROM CHECKTIME
WHERE CHECKTIME.EMPLOYEENO = C.EMPLOYEENO 
AND CHECKTIME.CheckTime < C.CheckTime) % 2 = 1 THEN 'O' ELSE CHECKTYPE END
FROM CHECKTIME C

SQL Fiddle attached.

András Ottó
  • 7,605
  • 1
  • 28
  • 38
  • the company uses SQL Server 2000 the "WITH" CLAUSE was not recognized.. do you have any workaround? – Dhenn Aug 28 '12 at 07:40
  • can you update it for me? as it is not clear to me yet.. do I have to input employeeno?.. can you make it automatic? as well as the ID? – Dhenn Aug 28 '12 at 07:58
  • You should input it the ID and the employeeno too. You can create a procedure with this two value and then you can update any of them – András Ottó Aug 28 '12 at 08:00
  • Hi Andras I'd like it to be in a loop whereas ID is on a select clause as well as the employeeno... – Dhenn Aug 28 '12 at 08:21
  • can you explain to me what does the update statement doing? I can't understand what is this for?AND CHECKTIME.ID < C.ID) % 2 = 1 THEN 'O' ELSE CHECKTYPE END – Dhenn Aug 30 '12 at 07:41
  • subquery return more than 1 results..cannot update it because of that. – Dhenn Aug 30 '12 at 07:44
  • It is just a simple COUNT, cannot give multiple lines. So please use the SQL Fiddle and show what you have, because I think you used somehow wrong. The inner select counts how many "older" records are in the db then the current one CHECKTIME.ID < C.ID AND if it is even then it stays I else it will be O – András Ottó Aug 30 '12 at 08:00
  • the records are updated nice! but It seems that the date doesn't matter.. I need it to be included, if I logged in tomorrow it should be have "I" but after updating the record are show as "O" after today's date..http://www.sqlfiddle.com/#!3/e6eff/2 – Dhenn Aug 30 '12 at 08:16
  • Check this, in your sql fiddel, you did not increased the ID the last two had 4. BUT you can use the Date also so a script like this may better for you: http://www.sqlfiddle.com/#!3/ad8f0/1 – András Ottó Aug 30 '12 at 08:34
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16024/discussion-between-andras-otto-and-dhenn) – András Ottó Aug 30 '12 at 11:27
  • Hi @Andra's Otto' , I've tested it and works fine.. but can you make it parametized so I can see the difference? Thanks! – Dhenn Aug 31 '12 at 01:26
  • Hi Dhenn! There is the paramaterized procedure. It is working for one entry. And I left there the update for ALL existing. You can replace the parameters with 'aa' and an ID for the inner update and try it in the SQL fiddle. – András Ottó Aug 31 '12 at 05:20
5

try this option (SQL Fiddle code), should be valid for MS SQL Server 2000.

And here you have the full working code, copy & paste on a SSMS tab. Use it to create your procedure.

DECLARE @Checktime TABLE([ID] int, [EmployeeNo] NVARCHAR(5), [CheckTime] datetime, [CheckType] NVARCHAR(1));

INSERT INTO @Checktime
    ([ID], [EmployeeNo], [CheckTime], [CheckType])
VALUES
(1, '111-1', '20120826 08:00:00', 'I'),
(2, '222-2', '20120826 08:05:00', 'I'),
(3, '333-3', '20120826 08:07:00', 'I'),
(4, '444-4', '20120826 08:09:00', 'I'),
(5, '555-5', '20120826 08:10:00', 'I'),
(6, '666-6', '20120826 08:12:00', 'I'),
(591, '050-71-1', '20120703 13:06:18', 'O'),
(592, '050-71-1', '20120703 13:06:16', 'O'),
(593, '050-71-1', '20120703 12:54:01', 'O'),
(594, '050-71-1', '20120703 12:53:59', 'O'),
(617, '050-71-1', '20120703 07:53:14', 'O'),
(631, '050-71-1', '20120702 17:36:12', 'O'),
(641, '050-71-1', '20120702 12:13:50', 'O'),
(642, '050-71-1', '20120702 12:13:49', 'O'),
(646, '050-71-1', '20120702 12:00:33', 'O'),
(647, '050-71-1', '20120702 12:00:31', 'O'),
(678, '050-71-1', '20120702 08:07:50', 'O'),
(679, '050-71-1', '20120828 18:07:48', 'O');

DECLARE @Employee NVARCHAR(5)='050-71-1'

INSERT INTO @Checktime ([ID], [EmployeeNo], [CheckTime], [CheckType])
SELECT TOP 1 680 'NewId', EmployeeNo, GETDATE(),
       'NewCheck' = CASE 
           WHEN DATEDIFF(dd, CheckTime, GETDATE())>0 THEN 'I'
           WHEN CheckType = 'I' THEN 'O'
           ELSE 'O'
       END
  FROM @Checktime
 WHERE EmployeeNo = @Employee
 ORDER BY CheckTime DES

SELECT * FROM @Checktime

Result:

ID  EmployeeNo          CheckTime          CheckType
1     111-1     2012-08-26 08:00:00.000       I
2     222-2     2012-08-26 08:05:00.000       I
3     333-3     2012-08-26 08:07:00.000       I
4     444-4     2012-08-26 08:09:00.000       I
5     555-5     2012-08-26 08:10:00.000       I
6     666-6     2012-08-26 08:12:00.000       I
7     222-2     2012-08-28 09:37:41.917       O
Yaroslav
  • 6,476
  • 10
  • 48
  • 89
  • Thanks Yaroslov! It worked .. I am now going to test it to server :) – Dhenn Aug 28 '12 at 07:47
  • You are welcome. Pay attention to the `INSERT INTO` as I forced the ID to be 7, but you have it as autonumeric so you don't need to include it on the `INSERT` clause – Yaroslav Aug 28 '12 at 07:50
  • You forced also the @Employee NVARCHAR(5)='222-2', how can I make it automatic and continuous ? – Dhenn Aug 28 '12 at 07:56
  • Yes, of course. That is why I commented that you should use the code to create the procedure, but changing whatever you need to meet your goal. In this case, the employe number should be a parameter passed to the procedure, or at least is what I think. That way the `INSERT` will be done for that employee. – Yaroslav Aug 28 '12 at 07:59
  • How to incorporate this in a loop in procedure?... do i need it in a while? I forgot to say that ID should not be entered by the user, it should be selected automatically as well as the employeeno...forgive me for asking too many questions... I am just new to sql..thanks – Dhenn Aug 28 '12 at 08:22
  • Automatically? And then how it will know wich new row should insert? Based on wich parameter? I mean, you want to have this procedure working continuosly until what happens, does it have an ending, wich should be the stop clause? I'm guessing here... Maybe what you need is a trigger that will do this job for you or will execute this procedure passing the employee number as parameter. And this trigger will be triggered by other action that somehow receives the employee number. At the end, you should know somehow wich employee you are adding to the table. – Yaroslav Aug 28 '12 at 08:35
  • I've tried this but the ony the "O" inserted, could this make happen that including I should be inserted? I want that all I and O should be inserted as well not the changed value only what happened: – Dhenn Aug 29 '12 at 01:33
  • ID EMPLOYEENO CHECKTIME CHECKTYPE 591 050-71-1 2012-07-03 13:06:18.000 O 592 050-71-1 2012-07-03 13:06:16.000 O 593 050-71-1 2012-07-03 12:54:01.000 O 594 050-71-1 2012-07-03 12:53:59.000 O 617 050-71-1 2012-07-03 07:53:14.000 O 631 050-71-1 2012-07-02 17:36:12.000 O 641 050-71-1 2012-07-02 12:13:50.000 O 642 050-71-1 2012-07-02 12:13:49.000 O 646 050-71-1 2012-07-02 12:00:33.000 O 647 050-71-1 2012-07-02 12:00:31.000 O 678 050-71-1 2012-07-02 08:07:50.000 O 679 050-71-1 2012-07-02 08:07:48.000 O – Dhenn Aug 29 '12 at 01:37
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15934/discussion-between-yaroslav-and-dhenn) – Yaroslav Aug 29 '12 at 06:54
  • check the chat, there are updates on the code to take into account the date as you requested – Yaroslav Aug 30 '12 at 08:23
4

I think it is better to use CheckIN & CheckOut columns instead of CheckTime & CheckType .

  • If he logged in already , update the checkOut time .

  • If he didn't log in , save the CheckIN & CheckOut time and it well be the same time in this case .

It can't be easer than this .

jjj
  • 605
  • 1
  • 9
  • 26