How can I get the date difference based on schedule of the employee and First Time In and Last Time Out?
Below are the queries I'm using.
select * from tbl_payroll_schedule where id in (3, 17, 18)
Output:
id schedule_description time_in time_out schedule_status
3 REST DAY 1900-01-01 00:00:00.000 1900-01-01 00:00:00.000 1
17 08:00 AM - 05:00 PM 1900-01-01 08:00:00.000 1900-01-01 17:00:00.000 1
18 08:00 AM - 12:00 PM 1900-01-01 08:00:00.000 1900-01-01 12:00:00.000 1
select mon.schedule_description as Monday,
tue.schedule_description as Tuesday,
wed.schedule_description as Wednesday,
thu.schedule_description as Thursday,
fri.schedule_description as Friday,
sat.schedule_description as Saturday,
sun.schedule_description as Sunday
from employee_default_schedule ds
LEFT JOIN tbl_payroll_schedule mon on mon.id = ds.mon_sched
LEFT JOIN tbl_payroll_schedule tue on tue.id = ds.tues_sched
LEFT JOIN tbl_payroll_schedule wed on wed.id = ds.wed_sched
LEFT JOIN tbl_payroll_schedule thu on thu.id = ds.thurs_sched
LEFT JOIN tbl_payroll_schedule fri on fri.id = ds.fri_sched
LEFT JOIN tbl_payroll_schedule sat on sat.id = ds.sat_sched
LEFT JOIN tbl_payroll_schedule sun on sun.id = ds.sun_sched
WHERE ds.employee_id = 125
Output:
select ot.id,
ot.employee_id as EID,
(el.Last_Name + ', ' + el.First_Name) as Name,
FORMAT(ot.record_time, 'ddd MM-dd-yyyy HH:mm:ss') as Time,
(CASE WHEN ot.type = 0 then 'Time In'
WHEN ot.type = 1 then 'Time Out'
END) as Status
from officer_timelogs ot
left join tbl_Employee_MasterList el on el.ID = ot.employee_id
where ot.employee_id = (CASE WHEN 125 = 0 THEN ot.employee_id else 125 END)
and ot.record_time >= CONVERT(datetime, '08/16/2018 00:00:00', 121) and ot.record_time <= CONVERT(datetime, '08/16/2018 23:59:59', 121)
order by el.Last_Name asc, ot.record_time asc
Output:
id EID Name Time Status
194664 125 MOQUETE, ABRAHAM JOSEPH Thu 08-16-2018 07:55:57 Time In
194703 125 MOQUETE, ABRAHAM JOSEPH Thu 08-16-2018 12:11:36 Time Out
194705 125 MOQUETE, ABRAHAM JOSEPH Thu 08-16-2018 12:28:12 Time In
194757 125 MOQUETE, ABRAHAM JOSEPH Thu 08-16-2018 20:45:08 Time Out
Currently I am able get the total work hours, and I want to get the Late and Overtime.
select
employee_id as EID,
FORMAT(date, 'MM-dd-yyyy') as [Date],
DATENAME(WEEKDAY, date) as [Day],
right(concat('00', diff / 4100), 2) + ':' + right(concat('00', diff % 3600 / 60), 2) + ':' + right(concat('00', diff % 60), 2) as TWH
from (select
employee_id,
[date] = cast(actual_time as date),
diff = datediff(ss, min(iif(type = 0, actual_time, null)), max(iif(type = 1, actual_time, null)))
from
officer_timelogs
where employee_id = (CASE WHEN #employee_id = 0 THEN employee_id else #employee_id END)
group by employee_id, cast(actual_time as date)
) t
where t.date >= #dateFrom and t.date <= #dateTo
order by date asc
Expected Output:
EID Date Day TWH Late OT
125 08-16-2018 Thursday 11:49:11
Related
Here is what my table looks like
ID | Date
------------
13 2013-03-21 00:00:00
13 2013-03-23 00:00:00
13 2013-03-24 00:00:00
25 2013-03-21 00:00:00
25 2013-03-22 00:00:00
25 2013-03-21 00:00:00
25 2013-03-23 00:00:00
25 2013-03-28 00:00:00
25 2013-03-21 00:00:00
82 2013-03-22 00:00:00
82 2013-03-22 00:00:00
I want it to output (combine sat & sun into 'weekend'). It'll combine all the Mondays, Tuesdays, Wednesdays, etc. and combine the values.
day | total
--------------
Friday 2
Thursday 3
Weekend 3
This is my query so far
SELECT
CASE
WHEN DATENAME(weekday, [date]) = 'Saturday' OR DATENAME(weekday, [date]) = 'Sunday' THEN 'Weekend'
ELSE DATENAME(weekday, [date])
END AS Day,
COUNT(DISTINCT [id]) AS score
FROM [table]
GROUP BY
CASE
WHEN DATENAME(weekday, [date]) = 'Saturday' OR DATENAME(weekday, [date]) = 'Sunday' THEN 'Weekend'
ELSE DATENAME(weekday, [date])
END
Currently I can get my query to output this, but it seems like it isn't adding both thursdays or sat + sun.
Day | total
--------------
Friday 2
Thursday 2
Weekend 2
Appears like what you are actually after is a distinct count of the ID and date combined. Seems like the easiest way, therefore, would be to concatenate the 2 values to make a new unique value and COUNT those DISTINCT values:
SELECT CASE WHEN DATENAME(WEEKDAY, V.[Date]) IN ('Saturday','Sunday') THEN 'Weekend' ELSE DATENAME(WEEKDAY, V.[Date]) END AS [Weekday],
COUNT(DISTINCT CONCAT(ID,[date]))
FROM (VALUES (13, CONVERT(datetime2(0),'2013-03-21T00:00:00')),
(13, CONVERT(datetime2(0),'2013-03-23T00:00:00')),
(13, CONVERT(datetime2(0),'2013-03-24T00:00:00')),
(25, CONVERT(datetime2(0),'2013-03-21T00:00:00')),
(25, CONVERT(datetime2(0),'2013-03-22T00:00:00')),
(25, CONVERT(datetime2(0),'2013-03-21T00:00:00')),
(25, CONVERT(datetime2(0),'2013-03-23T00:00:00')),
(25, CONVERT(datetime2(0),'2013-03-28T00:00:00')),
(25, CONVERT(datetime2(0),'2013-03-21T00:00:00')),
(82, CONVERT(datetime2(0),'2013-03-22T00:00:00')),
(82, CONVERT(datetime2(0),'2013-03-22T00:00:00'))) V (ID, [Date])
GROUP BY CASE WHEN DATENAME(WEEKDAY, V.[Date]) IN ('Saturday','Sunday') THEN 'Weekend' ELSE DATENAME(WEEKDAY, V.[Date]) END;
Try this!
select count(id)as Total,Day from
(
select id, case when Datename(weekday,dt1) IN('Saturday','Sunday') then 'Weekend' else Datename(weekday,dt1) end as 'Day' from tab
)x
group by Day
Demo here
select Day,Count(day) cnt from (
SELECT
CASE
WHEN DATENAME(weekday, [date]) = 'Saturday' OR DATENAME(weekday, [date]) = 'Sunday' THEN 'Weekend'
ELSE DATENAME(weekday, [date])
END AS Day
,[date]
FROM [Infinite_campus].[dbo].[AttendanceRecord]
) as t
group by Day
I have below tables called dailyshift,in 24 hours format
1 dailyshift
shiftid,employeeid,shiftdate ,starttime ,endtime hours
1 1 16th Aug 2019 , 08:00 15:00 7
2 1 18th Aug 2019 , 08:00 15:00 7
2 1 22th Aug 2019 , 08:00 15:00 7
3 2 17th Aug 2019 , 16:00 20:00 4
2 employeesalary
employeeid,salary, startdate , enddate
1 ,10, , 1st Aug 2019 , 16th Aug 2019
1 ,20, , 17st Aug 2019 , 20th Aug 2019
2 ,25, , 15st Aug 2019 , 20th Aug 2019
we need to have ouptput week wise salary total like, we need to make total salary by employee per week ,according to their configured salary per hour.
empleeid week weektotal
1 12th to 18th Aug 210
1 19th to 25th Aug 140
2 12th to 18th Aug 100
I have tried below but it is giving not accurate total
select employeeid,sum(d.hours*salary) as weektotal from dailyshift as d
inner join employeesalary as e
on d.employeeid=e.employeeid
group by employeeid
can we have way to make this?
Query may seems complex, but if you go through part by part, you will understand everything. CTE and CTE2 is just use for date manipulation to get the desired result.
WITH CTE AS(
SELECT *,
DATEADD(DAY, 1 - IIF(DATEPART(WEEKDAY, CAST(REPLACE(REPLACE(REPLACE(REPLACE(shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME))-1 = 0,7,
DATEPART(WEEKDAY, CAST(REPLACE(REPLACE(REPLACE(REPLACE(shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME))-1),
CAST(REPLACE(REPLACE(REPLACE(REPLACE(shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME)) [Week_Start_Date],
DATEADD(DAY, 7 - IIF(DATEPART(WEEKDAY, CAST(REPLACE(REPLACE(REPLACE(REPLACE(shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME))-1 = 0,7,
DATEPART(WEEKDAY, CAST(REPLACE(REPLACE(REPLACE(REPLACE(shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME))-1),
CAST(REPLACE(REPLACE(REPLACE(REPLACE(shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME)) [Week_End_Date]
FROM dailyshift
),
CTE2 AS(
SELECT A.shiftid,A.employeeid,A.shiftdate,A.starttime,A.endtime,A.hours,
CAST(DAY(Week_Start_Date) AS VARCHAR)+
CASE
WHEN DAY(Week_Start_Date) % 100 IN (11,12,13) THEN 'th ' --first checks for exception
WHEN DAY(Week_Start_Date) % 10 = 1 THEN 'st '
WHEN DAY(Week_Start_Date) % 10 = 2 THEN 'nd '
WHEN DAY(Week_Start_Date) % 10 = 3 THEN 'rd '
ELSE 'th ' --works for num % 10 IN (4,5,6,7,8,9,0)
END
+'To '+
CAST(DAY(Week_End_Date) AS VARCHAR) +
CASE
WHEN DAY(Week_End_Date) % 100 IN (11,12,13) THEN 'th ' --first checks for exception
WHEN DAY(Week_End_Date) % 10 = 1 THEN 'st '
WHEN DAY(Week_End_Date) % 10 = 2 THEN 'nd '
WHEN DAY(Week_End_Date) % 10 = 3 THEN 'rd '
ELSE 'th ' --works for num % 10 IN (4,5,6,7,8,9,0)
END +
LEFT(DATENAME(Month,Week_End_Date),3) +' '+
CAST(YEAR(Week_End_Date) AS VARCHAR) grp_clm_name
FROM CTE A
)
SELECT A.employeeid,
A.grp_clm_name Week,
SUM(A.hours*B.salary) WeekTotal
FROM CTE2 A
INNER JOIN employeesalary B
ON A.employeeid = B.employeeid
AND CAST(REPLACE(REPLACE(REPLACE(REPLACE(A.shiftdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME)
BETWEEN CAST(REPLACE(REPLACE(REPLACE(REPLACE(B.startdate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME)
AND CAST(REPLACE(REPLACE(REPLACE(REPLACE(B.enddate,'st ','-'),'nd ','-'),'rd ','-'),'th ','-') AS DATETIME)
GROUP BY A.employeeid, A.grp_clm_name
ORDER BY 1
Output is-
employeeid Week eekTotal
1 2th To 18th Aug 2019 210
2 12th To 18th Aug 2019 100
Row with value "1 19th to 25th Aug 140" is missing as you have no salary definition for employee 1 for date 22th Aug 2019
You need the applicable salary for the shift date so you need to do the following:
select d.employeeid, sum(d.hours * e.salary) as weektotal
from dailyshift as d
inner join employeesalary as e
on d.employeeid = e.employeeid
and d.shiftdate >= e.startdate
and d.shiftdate <= e.endate
group by d.employeeid
Assuming EmployeeSalary tables contains the hourly salary of employees, each employee can have different salary for different period.
Following query must give you expected result:
select employeeid,
DATEADD(day, -(DATEPART(dw, d.shiftdate)-1), d.shiftdate) [WeekStart],
DATEADD(day, 7-(DATEPART(dw, d.shiftdate)), d.shiftdate) [WeekEnd],
sum(d.hours*salary) as Weektotal
from dailyshift as d
inner join employeesalary as e
on d.employeeid=e.employeeid and d.shiftdate between e.startdate and e.enddate
group by employeeid, DATEADD(day, -(DATEPART(dw, d.shiftdate)-1), d.shiftdate), DATEADD(day, 7-(DATEPART(dw, d.shiftdate)), d.shiftdate)
I have a SQL statement (MS SQL Server 2012) that makes a simple calculation of the differences in dates in some records. I want to return the total / sum of the DATEDIFFs as well.
This is my query:
with cte as (
select ROW_NUMBER () OVER (ORDER BY Date) as ID, Die_ID, Date, Status
from Tooling_Status
where (date between '2018-02-27 00:00:00' and '2019-02-27 11:59:59')
and Date is not null)
select DATEDIFF (ss, c1.Date, min (c2.Date)) as Seconds, convert (nvarchar (10), c1.Date, 120) as DIA
from cte c1
left outer join cte c2
on c1.Date < c2.Date and c1.Die_ID = c2.Die_ID
where c1.Status = 2 and c2.Status = 1
group by c1.Date
order by DIA desc
And this my result:
Seconds DAY
2253 2019-02-27
166 2019-02-27
17 2019-02-27
104 2019-02-27
36 2019-02-27
11 2019-02-07
20 2019-02-07
32 2019-02-07
22 2019-02-07
27 2019-02-07
33 2019-02-07
15 2019-02-07
34 2019-02-07
120 2019-02-04
99420 2019-01-07
60 2018-09-26
I need this result:
Seconds DAY
2732 2019-02-27
194 2019-02-07
120 2019-02-04
99420 2019-01-07
60 2018-09-26
Thanks For Help!
Few adjustments
Extra GROUP BY using a derived table
Removed unnecessary casts to a string
Formatting...
SQL:
WITH cte
AS (SELECT ROW_NUMBER() OVER (ORDER BY Date) AS ID,
Die_ID,
Date,
Status
FROM Tooling_Status
WHERE (date BETWEEN '2018-02-27 00:00:00' AND '2019-02-27 11:59:59' )
AND Date IS NOT NULL
)
SELECT SUM(d.Seconds) AS Seconds
, d.DIA AS [Day]
FROM (
SELECT DATEDIFF(ss, c1.Date, MIN(c2.Date)) AS Seconds,
CAST(c1.Date AS DATE) AS DIA
FROM cte c1
LEFT OUTER JOIN cte c2
ON c1.Date < c2.Date
AND c1.Die_ID = c2.Die_ID
WHERE c1.Status = 2 AND c2.Status = 1
GROUP BY c1.Date
) d
GROUP BY d.DIA
ORDER BY [Day] DESC;
We have a list of items. Each item may be checked/examined one or more times in the last #FromDate to #ToDate (12 months, for example). How do we count the number of items which were checked in a month that had never been check since #FromDate and display that count monthly.
The result would look like below:
2014-05-01 00:00:00.000 1 May 2014 381
2014-06-01 00:00:00.000 2 June 2014 296
2014-07-01 00:00:00.000 3 July 2014 24
2014-08-01 00:00:00.000 4 August 2014 260
2014-09-01 00:00:00.000 5 September 2014 249
2014-10-01 00:00:00.000 6 October 2014 177
2014-11-01 00:00:00.000 7 November 2014 298
2014-12-01 00:00:00.000 8 December 2014 274
2015-01-01 00:00:00.000 9 January 2015 41
2015-02-01 00:00:00.000 10 February 2015 0
2015-03-01 00:00:00.000 11 March 2015 0
2015-04-01 00:00:00.000 12 April 2015 0
So far we could count the number of items which were checked monthly by using the following query:
;WITH d AS
(
SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, '2014-05-15'), 0)) as d, ROW_NUMBER() OVER (ORDER BY n) as rn
FROM ( SELECT TOP (DATEDIFF(MONTH, '2014-05-15', '2015-04-15') + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT
d.d,
d.rn,
DATENAME(MONTH, d.d) as [Month],
YEAR(d.d) as [Year],
COUNT(DISTINCT ItemNumber) AS Count
FROM d LEFT OUTER JOIN ItemCheck
ON CheckedTime >= d.d
AND CheckedTime < DATEADD(MONTH, 1, d.d)
GROUP BY d.d, d.rn
ORDER BY d.d;
However, we still can't figure out how to count the number of items which were checked say in July 2014 but had never been checked in May and June 2014.
A simple single query below would be able to display that for a particular month but that doesn't display in monthly.
select count(distinct ItemNumber) from ItemCheck
where CheckTime >= '2014-07-01' AND CheckTime < '2014-08-01' and
ItemNumber NOt in (SELECT ItemNumber FROM ItemCheck as t1 where t1.CheckTime >= '2014-05-01' AND t1.CheckTime < '2014-07-01')
order by ItemNumber
Update: The ItemCheck table looks like below:
CheckID | ItemNumber | CheckTime
1 i1 2014-05-02
2 i4 2014-06-12
3 i5 2014-07-03
4 i1 2014-08-01
5 i1 2014-08-02
6 i2 2014-09-15
7 i3 2014-10-11
Suppose you have a table called months with one column called month.
Then you could do it something along these lines:
DECLARE #date DATE
SET #date = '2014-01-01'
SELECT months.month AS currentMonth, COUNT(ItemNumber) ItemNumber from ItemCheck
CROSS JOIN months
WHERE CheckTime >= dateadd(m, months.month - 1, #date) AND CheckTime < dateadd(m, months.month, #date) and
ItemNumber NOT IN (SELECT ItemNumber FROM ItemCheck AS t1 WHERE t1.CheckTime >= DATEADD(m, months.month - 3, #date) AND t1.CheckTime < dateadd(m, months.month - 1, #date))
GROUP BY month
ORDER BY ItemNumber
You could also do it with a function, but you have to write it (function is called dbo.Split and you could write it this way: select data from dbo.Split(',', '1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12'). This way you could avoid creating another table (in-memory or a real one..)
If you want the code for dbo.Split I can provide it.
I need to split these dates by FY and get the number of months between the dates. I have the FY split answered previously at How to duplicate Rows with new entries link.
Having the following dates:-
ID Start dt End dt
2550 10/1/2010 9/30/2011
2551 8/1/2014 7/31/2015
2552 6/1/2013 5/31/2015
2553 5/10/2012 6/11/2014
I would like the following result set:
ID FY # of Months Start Dt End Dt
2550 2011 12 10/1/2010 9/30/2011
2551 2014 2 8/1/2014 9/30/2014
2551 2015 10 10/1/2014 7/31/2015
2552 2013 4 6/1/2013 9/30/2013
2552 2014 12 10/1/2013 9/30/2014
2552 2015 8 10/1/2014 5/31/2015
2553 2012 5 5/10/2012 9/30/2012
2553 2013 12 10/1/2012 9/30/2013
2553 2014 9 10/1/2013 6/11/2014
An FY is considered from Oct to Sept of the next year.
Thanks in advance!
It was a fun query to build:
declare #t table(id int, start_dt datetime, end_dt datetime)
Insert into #t(id, start_dt, end_dt) Values
(2550, '2010/10/1', '2011/9/30')
, (2551, '2014/8/1', '2015/7/31')
, (2552, '2013/6/1', '2015/5/31')
, (2553, '2012/5/10', '2014/6/11')
, (2554, '2012/5/10', '2012/11/1')
, (2555, '2012/5/10', '2012/8/11')
; with data as(
Select id, start_dt, end_dt, next_y = DATEADD(month, 9, DATEADD(year, DATEDIFF(year, 0, DATEADD(month, 3, start_dt)), 0))
From #t
), split as (
Select id, start_dt
, end_dt = case when next_y > end_dt then end_dt else DATEADD(day, -1, next_y) end
, next_y = DATEADD(year, 1, next_y)
From data as d
Union All
Select s.id
, DATEADD(day, 1, s.end_dt)
, case when DATEADD(day, -1, next_y) < t.end_dt then DATEADD(day, -1, next_y) else t.end_dt end
, next_y = DATEADD(year, 1, s.next_y)
From split as s
Inner Join #t as t on t.id = s.id
Where s.end_dt < t.end_dt
)
Select ID, FY = year(end_dt), '# of Months' = DATEDIFF(month, start_dt, end_dt)+1, 'Start Dt' = start_dt, 'End Dt' = end_dt
From split
Order by id, start_dt, end_dt