Reputation: 170
I have a table EmpLunch like below:
EmployeeId BusinessDate PunchIn Lunch1Start Lunch1End Lunch2Start Lunch2End PunchOut
101 10/12/2017 9:00 AM 1:00 PM 1:30 PM 5:00 PM
101 10/13/2017 9:00 AM 1:00 PM 1:28 PM 5:00 PM
101 10/14/2017 9:00 AM 1:00 PM 1:28 PM 3:00 PM 3:28 PM 5:00 PM
101 10/15/2017 9:00 AM 5:00 PM
I need to populate the data in one additional column ErrorCode based on following logic:
Error Code =
1 = Lunch 1 Not Taken
2 = Lunch 1 Less Than 30 Minutes
3 = Lunch 1 Started 300 Minutes Past IN Punch
4 = Lunch 2 Not Taken
5 = Lunch 2 Less Than 30 Minutes
The resultant table sould be like:
EmployeeId BusinessDate PunchIn Lunch1Start Lunch1End Lunch2Start Lunch2End PunchOut ErrorCode
101 10/12/2017 9:00 AM 1:00 PM 1:30 PM 5:00 PM 4
101 10/13/2017 9:00 AM 1:00 PM 1:28 PM 5:00 PM 2, 4
101 10/14/2017 9:00 AM 1:00 PM 1:28 PM 3:00 PM 3:28 PM 5:00 PM 2, 5
101 10/15/2017 9:00 AM 5:00 PM 1
I have written a simple code like below:
Select *,
CASE WHEN Lunch1Start IS NULL THEN '1'
WHEN DATEDIFF(MINUTE, Lunch1Start, Lunch1End) < 30.0 THEN '2'
WHEN DATEDIFF(MINUTE, LunchEnd1, PunchIn) < 300.0 THEN '3'
WHEN Lunch2Start IS NULL THEN '4'
WHEN DATEDIFF(MINUTE, Lunch2End, LunchI2Start) < 30.0 THEN '5'
END LunchError
From EmpLunch
The above query is not giving multiple records in a cell (like record for 10/13 and 10/14 in above resultant table). My query is giving out just the first value in the column. Please suggest a way to achieve the goal (comma separated multiple values in column).
Upvotes: 2
Views: 140
Reputation: 189
Mine works:
DROP TABLE IF EXISTS category --SQL 2016/17
go
CREATE TABLE Category
(id int IDENTITY (1,1) NOT NULL Primary Key
,Punchin time
,lunch1Start time
,lunch1End time
,lunch2Start time
,lunch2End time
,Punchout time
,LunchError as CASE when lunch1start is null then '1' WHEN DATEDIFF(MINUTE,lunch1start,lunch1end) < 30 THEN '2'
WHEN DATEDIFF(MINUTE,lunch1end, punchin) < 300 THEN '3'
WHEN lunch2start is null then '4' end
+ ', '+ CASE WHEN lunch2start is null then '4' WHEN DATEDIFF(MINUTE,lunch2start,lunch2end) < 30 THEN '5'
WHEN DATEDIFF(MINUTE,lunch2start,lunch2end) < 300 THEN '3'
END
)
INSERT category(punchin, lunch1Start, lunch1End, Punchout)
VALUES ('9:00 am','1:00 pm', '1:30 pm', '5:00 pm')
INSERT category(punchin, lunch1Start, lunch1End, Punchout)
VALUES('9:00 am','1:00 pm', '1:28 pm', '5:00 pm')
INSERT category(punchin, lunch1Start, lunch1End, lunch2Start, lunch2End, Punchout)
VALUES ('9:00 am','1:00 pm', '1:28 pm', '3:00 pm', '3:28','5:00 pm')
INSERT category(punchin, Punchout)
VALUES ('9:00 am','5:00 pm')
Upvotes: 0
Reputation: 1269873
You can get the separate values using separate case
expressions concatenated together. Here is one method:
select el.*,
stuff( (case when Lunch1Start is null then ', 1' else '' end) +
(case when datediff(minute, Lunch1Start, Lunch1End) < 30 then ', 2' else '' end) +
(case when datediff(minute, LunchEnd1, PunchIn) < 300 then ', 3' else '' end) +
(case when Lunch2Start IS NULL then ', 4' else '' end) +
(case when datediff(minute, Lunch2End, LunchI2Start) < 30 then ', 5' else '' end), 1, 2, '')
from EmpLunch el;
The stuff()
removes the separators. Also note that this version returns an empty string -- rather than NULL
-- if there are no errors. If you want NULL
, then use nullif()
:
select el.*,
nullif(stuff( (case when Lunch1Start is null then ', 1' else '' end) +
(case when datediff(minute, Lunch1Start, Lunch1End) < 30 then ', 2' else '' end) +
(case when datediff(minute, LunchEnd1, PunchIn) < 300 then ', 3' else '' end) +
(case when Lunch2Start IS NULL then ', 4' else '' end) +
(case when datediff(minute, Lunch2End, LunchI2Start) < 30 then ', 5' else '' end), 1, 2, ''), '')
from EmpLunch el;
Note that datediff()
returns an integer. It also may not do exactly what you want, because it counts "unit boundaries" between values. I would use this logic instead:
select el.*,
stuff( (case when Lunch1Start is null then ', 1' else '' end) +
(case when Lunch1Start < dateadd(minute, -30, Lunch1End) then ', 2' else '' end) +
(case when LunchEnd1 < dateadd(minute, -300) < 300 then ', 3' else '' end) +
(case when Lunch2Start IS NULL then ', 4' else '' end) +
(case when Lunch2End < dateadd(minute, -30, LunchI2Start) then ', 5' else '' end), 1, 2, '')
from EmpLunch el;
Upvotes: 3
Reputation: 4146
You just need to concat result of three differenct cases. First for error codes 1 and 2, second for error code 3 and third for codes 4 and 5. Like this:
Select
*, STUFF(CASE WHEN Lunch1Start IS NULL THEN ', 1' WHEN DATEDIFF(MINUTE, Lunch1Start, Lunch1End) < 30.0 THEN ', 2' ELSE '' END
+ CASE WHEN DATEDIFF(MINUTE, LunchEnd1, PunchIn) < 300.0 THEN ', 3' ELSE '' END
+ CASE WHEN Lunch2Start IS NULL THEN ', 4' WHEN DATEDIFF(MINUTE, Lunch2End, LunchI2Start) < 30.0 THEN ', 5' ELSE '' END,1,2,'') LunchError
From EmpLunch
Upvotes: 3