Related
I have time stored in minutes in integer datatype which has to be displayed in HH:MM format. For example: if total minutes is 80 then it should convert to 01:20.
select SUM(OTTime) from dbo.TableOT where ....
I have tried some queries but didn't get the exact output.
Updated Query:
SELECT SUM(t.OTTime),d.combovalue
FROM dbo.employee e
join dbo.OT t
on e.id = t.employeeid
JOIN dbo.combovalues d
ON e.department = d.id
GROUP By d.combovalue
Try this Single Query:
DECLARE #Duration int
SET #Duration= 4000
SELECT CAST( CAST((#Duration) AS int) / 60 AS varchar) + ':' + right('0' + CAST(CAST((#Duration) AS int) % 60 AS varchar(2)),2)
For Updated Query:
SELECT d.combovalue,CAST(CAST((SUM(t.OTTime)) AS int) / 60 AS varchar) + ':'
+ right('0' + CAST(CAST((SUM(t.OTTime)) AS int) % 60 AS varchar(2)),2)
FROM dbo.employee e join dbo.OT t on e.id = t.employeeid
JOIN dbo.combovalues d ON e.department = d.id
GROUP By d.combovalue
Instead of #minutes variable you can use SUM(OTTime) and a from clause in this below Query
DECLARE #minutes INT=80
SELECT CASE WHEN #minutes >= 60 THEN (SELECT CAST((#minutes / 60) AS VARCHAR(2)) + ':' + CASE WHEN (#minutes % 60) > 0 THEN CAST((#minutes % 60) AS VARCHAR(2))
ELSE '' END)
ELSE CAST((#minutes % 60) AS VARCHAR(2)) END
For Eg:
SELECT CASE WHEN SUM(OTTime) >= 60 THEN (SELECT CAST((SUM(OTTime) / 60) AS VARCHAR(2)) + ':' + CASE WHEN (SUM(OTTime) % 60) > 0 THEN CAST((SUM(OTTime) % 60) AS VARCHAR(2))
ELSE '' END)
ELSE CAST((SUM(OTTime) % 60) AS VARCHAR(2)) END
from dbo.TableOT where ....
Create a SCALAR Function and pass the
select dbo.Minutes_to_HrsMts (SUM(OTTime)) from dbo.TableOT where ....
Function:
CREATE Function dbo.Minutes_to_HrsMts (#minutes INT)
RETURNS nvarchar(30)
AS
BEGIN
declare #hours nvarchar(20)
SET #hours =
CASE WHEN #minutes >= 60 THEN
(SELECT CAST((#minutes / 60) AS VARCHAR(2)) + ':' +
CASE WHEN (#minutes % 60) > 0 THEN
CAST((#minutes % 60) AS VARCHAR(2))
ELSE
''
END)
ELSE
CAST((#minutes % 60) AS VARCHAR(2))
END
return #hours
END
First, I recommend using decimal hours. Much simpler:
SELECT d.combovalue, SUM(t.OTTime) / 60.0
FROM dbo.employee e JOIN
dbo.OT t
ON e.id = t.employeeid JOIN
dbo.combovalues d
ON e.department = d.id
GROUP By d.combovalue;
But that is not your question. If you knew that there are never more than 24 hours, you could use the TIME data type:
CONVERT(VARCHAR(5), DATEADD(minute, SUM(t.OTTime), 0), 8)
If that is too dangerous, then you need to convert to a string:
CONCAT(FORMAT(SUM(t.OTTime) / 60, '00'), ':', FORMAT(SUM(t.OTTime) % 60, '00'))
I keep getting the above error message
"Operand data type varchar is invalid for avg operator"
Can anyone fix it for me? PLEASE
WITH Average -- Calculating Mean
AS (
SELECT avg(convert(VARCHAR(5), DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME]) / 3600) + ':' + convert(VARCHAR(5), DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME]) % 3600 / 60) + ':' + convert(VARCHAR(5), (DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME]) % 60))) AS Average
FROM [CLERKS]
WHERE [ARRIVAL_DATE_TIME] >= DATEADD(dd, - 30, getdate() - 1)
)
,data
AS (
SELECT cast(ARRIVAL_DATE_TIME AS DATE) AS Attendance_Date
,avg(convert(VARCHAR(5), DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME]) / 3600) + ':' + convert(VARCHAR(5), DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME]) % 3600 / 60) + ':' + convert(VARCHAR(5), (DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME]) % 60))) AS Arr_Com
FROM [Clerks]
WHERE [ARRIVAL_DATE_TIME] >= DATEADD(dd, - 30, getdate() - 1)
GROUP BY cast(ARRIVAL_DATE_TIME AS DATE)
)
SELECT a.Attendance_Date
,a.Arr_Com
,c.Average
,abs(a.Arr_Com - b.Arr_Com) AS MR
FROM data a
LEFT JOIN data b ON cast(a.Attendance_Date AS DATETIME) = cast(b.Attendance_Date AS DATETIME) + 1
CROSS JOIN Average c
ORDER BY a.Attendance_Date
GO
Thanks in Advance
Actually, the problem is that the implementation is incorrect. You don't want to average timestamps (5h:3m:20s), but durations.
Hence, you need to calculate the duration in the smallest denominator, in your case seconds, calculate the average in seconds, by using the AVG() function and then formatting that result to look like hh:mm:ss.
Your code should look like:
;WITH Average -- Calculating Mean
AS (
SELECT AVG(DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME])) as Average
FROM [CLERKS]
WHERE [ARRIVAL_DATE_TIME] >= DATEADD(dd, - 30, getdate() - 1)
)
,data
AS (
SELECT cast(ARRIVAL_DATE_TIME AS DATE) AS Attendance_Date
, AVG(DateDiff(s, [ARRIVAL_DATE_TIME], [COMPLETE_DATE_TIME])) as Arr_Com
FROM [Clerks]
WHERE [ARRIVAL_DATE_TIME] >= DATEADD(dd, - 30, getdate() - 1)
GROUP BY cast(ARRIVAL_DATE_TIME AS DATE)
)
SELECT
Attendance_Date
, Arr_Com
, Average
, avg(convert(VARCHAR(5), MR / 3600) + ':' + convert(VARCHAR(5), MR % 3600 / 60) + ':' + convert(VARCHAR(5), MR % 60))) AS MR
FROM (
SELECT a.Attendance_Date
,a.Arr_Com
,c.Average
, abs(a.Arr_Com - b.Arr_Com) AS MR
FROM data a
LEFT JOIN data b ON cast(a.Attendance_Date AS DATETIME) = cast(b.Attendance_Date AS DATETIME) + 1
CROSS JOIN Average c
) tmp
ORDER BY Attendance_Date
I have an attendance table with the result as shown below
I need to get the result in below format:
Below is sample PIVOT query I used. Please help me with a query to get the desired result.
CREATE TABLE #Temp
(
[empcode] varchar(15),
[empDesc] nvarchar(300),
[hrlog_Date] date,
[hrlog_in] datetime,
[hrlog_Out] datetime,
[hrlog_Latein] datetime,
[hrlog_EarlyOut] datetime,
)
DECLARE #Start datetime,#End datetime,#DList varchar(2000),#Sql varchar(max),#Sql1 varchar(max);
SET #Start=#StartDate;
SET #End=#EndDate;
INSERT INTO #Temp
Select h.emp_code,e.emp_desc as emp_Desc,h.hrlog_Date, CONVERT(datetime,h.hrlog_in, 105) as hrlog_in
,CONVERT(datetime,h.hrlog_out,105) as hrlog_out
,
case when cast(h.hrlog_in as time)> cast('8:45' as time) then
cast(h.hrlog_Date as NVARCHAR(50))+' ' +CAST(DATEDIFF(second, cast('8:45' as time), cast(h.hrlog_in as time) ) / 60 / 60 % 24 AS NVARCHAR(50))+ ':' +
CAST(DATEDIFF(second,cast('8:45' as time), cast(h.hrlog_in as time) ) / 60 % 60 AS NVARCHAR(50))
else cast(h.hrlog_Date as nvarchar(50)) +' 0:00' end
mrngLate
,case when cast(h.hrlog_out as time) < cast('17:15' as time) then
cast(h.hrlog_Date as NVARCHAR(50))+' ' +CAST(DATEDIFF(second, cast(h.hrlog_out as time), cast('17:15' as time) ) / 60 / 60 % 24 AS NVARCHAR(50))+ ':' +
CAST(DATEDIFF(second, cast(h.hrlog_out as time),cast('17:15' as time) ) / 60 % 60 AS NVARCHAR(50))
else cast(h.hrlog_Date as nvarchar(50)) +' 0:00' end EvenEarly
from HRDailyLog h INNER JOIN FTEmployee e ON h.emp_code=e.Emp_Code
LEFT OUTER JOIN sys_CostCenterDep c ON e.sys_ccdepcode = c.sys_ccDepCode
LEFT OUTER JOIN FTJobDesc j ON e.job_code = j.Job_code
LEFT OUTER JOIN sysDep d ON j.sys_depcode = d.Sys_Depcode
LEFT OUTER JOIN HrShift s ON e.SFT_Code = s.SFT_Code
Where (h.hrlog_date between #Start and #End and e.SFT_Code is not null)
and CASE WHEN #sftCode = '-1' then #sftCode else e.SFT_Code end= #sftCode
and CASE WHEN #depCode = '-1' then #depCode else d.Sys_Depcode end= #depCode
and h.sys_bRcode = #brCode
SELECT DATEADD(dd,number,#Start) AS Date INTO #Date
FROM master..spt_values
WHERE type='p'
AND DATEADD(dd,number,#Start)<=#End
SELECT #DList=LEFT(dl.Dates,LEN(dl.Dates)-1)
FROM
(SELECT CAST(Date as varchar(11)) + ','
FROM #Date
FOR XML PATH('')
)dl(Dates)
SET #Sql='SELECT * FROM (
SELECT d.Date as dateIn ,t.empcode as empcode,t.empDesc as empDesc,(CONVERT(nvarchar(5),t.hrlog_in, 108)+'' to ''+CONVERT(nvarchar(5),t.hrlog_Out, 108)) as hrlog_in
FROM #Date d
LEFT JOIN #Temp t
ON CONVERT(nvarchar(10), t.hrlog_in, 111)=d.Date
)tm
PIVOT (MIN(hrlog_in) FOR dateIn IN ([' + REPLACE(#DList,',','],[')+ ']))p
WHERE empcode IS NOT NULL'
EXEC(#Sql)
I am trying to show my team's productivity vs non-productivity percentages based of what type of work they perform throughout the day. I can successfully achieve the format i am looking for with the below code but if an associate is productive in 2 separate departments in 1 day the sub-query fails because it returns multiple rows.
This is what im working with now
DECLARE
#Offset INT ,
#Start DATETIME ,
#Loc INT ,
#NON time(0) ,
#PROD time(0) ,
#TOTAL TIME(0)
SET #Offset = 4
SET #Start = dateadd(day, datediff(day, 0, getdate()), -#Offset)
--SUM OF ALL DEPT CATEGORIES WORKED FOR SELECTED DATE RANGE
select Codes = (DeptCode + ' ' + Opcode)
, TimeSum = right(convert(varchar(9),(sum(datediff(second,StartTime,FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,StartTime,FinishTime)) / 60) % 60 ),2)
, Units = sum(units)
FROM TimeLogNEW
where EventDate = #Start and Location = 10 and ID = 2372013
group by EventDate, id, DeptCode, OpCode
--SUM OF NON PRODUCTIVE HOURS WORKED (HAVING A UNITS SUM OF '0' IS CONSIDERED NON PRODUCTIVE) --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set #NON =
(select NonProd = right(convert(varchar(9),(sum(datediff(second,'0:00:00',TimeSum)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,'0:00:00',TimeSum)) / 60) % 60 ),2)
from (select
TimeSum = right(convert(varchar(9),(sum(datediff(second,m.StartTime,m.FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,m.StartTime,m.FinishTime)) / 60) % 60 ),2)
,Units = sum(m.units)
FROM TimeLogNEW m
where m.EventDate = #Start and opCode Not in ('ll') and m.Location = 10 and m.ID = 2372013
group by m.EventDate, m.id, m.DeptCode, m.OpCode
)t Group By Units Having Units = 0)
select #NON as 'NON-PROD_Hours'
--SUM OF PRODUCTIVE HOURS WORKED (HAVING A UNITS SUM OF MORE THAN '0' IS CONSIDERED PRODUCTIVE) --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set #PROD =
(select TotalProd = right(convert(varchar(9),(sum(datediff(second,'0:00:00',TimeSum)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,'0:00:00',TimeSum)) / 60) % 60 ),2)
from (select
TimeSum = right(convert(varchar(9),(sum(datediff(second,m.StartTime,m.FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,m.StartTime,m.FinishTime)) / 60) % 60 ),2)
,Units = sum(m.units)
FROM TimeLogNEW m
where m.EventDate = #Start and opCode Not in ('ll') and m.Location = 10 and m.ID = 2372013
group by m.EventDate, m.id, m.DeptCode, m.OpCode
)t Group By Units Having Units >0 )
select #PROD as 'PROD_Hours'
--SUM OF ALL HOURS WORKED --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set #TOTAL =
(select
TotalTime_NoLunch = right(convert(varchar(9),(sum(datediff(second,StartTime,FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,StartTime,FinishTime)) / 60) % 60 ),2)
FROM TimeLogNEW
where EventDate = #Start and ID = 2372013 and OpCode not in ('ll'))
select #TOTAL as 'SUM_Hours'
--PERCENTAGE OF PRODUCTIVITY
select
[Prod%] =convert(varchar(30),(100 *datediff(minute,'0:00:00',#PROD)/datediff(minute,'0:00:00',#TOTAL) )) +'%'
--PERCENTAGE OF NON-PRODUCTIVITY
select
[NON Prod%] =convert(varchar(30),(100 *datediff(minute,'0:00:00',#NON)/datediff(minute,'0:00:00',#TOTAL) )) +'%'
Result shown. For 7-2-18
If more than 1 of the dept categories codes has greater than 0 Units the sub-query fails. I have been trying to re-arrange the query to allow the grouping of sums equaling 0 and sums having greater than 0, but am stumped here. I am not getting correct results when ungrouping the Units column in the sub.
Here is what the raw data looks like with more than 1 productive operation. 7-3-18
The problem is that you group by DeptCode and OpCode but do not sum these results over the groups. Try this:
DECLARE
#Offset INT ,
#Start DATETIME ,
#Loc INT = 10 ,
#NON INT ,
#PROD INT ,
#TOTAL INT
SET #Offset = 4;
SET #Start = DATEADD(day, DATEDIFF(day, 0, GETDATE()), -#Offset);
--SUM OF ALL DEPT CATEGORIES WORKED FOR SELECTED DATE RANGE
WITH
TimeLog (EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, SUM(Units)
, SUM(DATEDIFF(second, StartTime, FinishTime))
FROM TimeLogNEW
GROUP BY EventDate, [Location], ID, DeptCode, OpCode
)
SELECT
Codes = (DeptCode + ' ' + Opcode)
, TimeSum = CAST(DATEADD(second, Seconds, 0) AS time(0))
, Units
FROM TimeLog
WHERE EventDate = #Start AND [Location] = #Loc AND ID = 2372013;
WITH
TimeLog (EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, SUM(Units)
, SUM(DATEDIFF(second, StartTime, FinishTime))
FROM TimeLogNEW
GROUP BY EventDate, [Location], ID, DeptCode, OpCode
),
TimeSplit (EventDate, Loc, ID, DC, OC, Units, Seconds, NON_PROD, PROD) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds
, CASE WHEN Units = 0 THEN Seconds ELSE 0 END
, CASE WHEN Units > 0 THEN Seconds ELSE 0 END
FROM TimeLog
)
SELECT #NON = SUM(NON_PROD), #PROD = SUM(PROD), #TOTAL = SUM(Seconds)
FROM TimeSplit
WHERE EventDate = #Start AND Loc = #Loc AND ID = 2372013 AND OC NOT IN ('LL');
-- RESULTS
SELECT
CONVERT(nvarchar(30), #NON/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, #NON, 0), 108), 6) AS 'NON-PROD_Hours',
CONVERT(nvarchar(30), #PROD/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, #PROD, 0), 108), 6) AS 'PROD_Hours',
CONVERT(nvarchar(30), #TOTAL/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, #TOTAL, 0), 108), 6) AS 'SUM_Hours',
CAST(100.0 * #PROD / #TOTAL AS varchar(30)) +'%' AS 'Prod%',
CAST(100.0 * #NON / #TOTAL AS varchar(30)) +'%' AS 'NON Prod%';
How to display only hours and minutes in a field if I get them separately
[SELECT
D.numOperador,
SUM(DATEDIFF(MINUTE, D.FechaSalida, D.FechaLlegada)) / 60 AS \[Horas\] ,
SUM(DATEDIFF(MINUTE, D.FechaSalida, D.FechaLlegada)) % 60 AS \[Minutos\]
FROM
trkOperadores O
INNER JOIN trfDespacho D ON O.NumOperador = D.numOperador
WHERE
O.cveTipoOperador = 2
AND O.NumOperador = 900200
AND D.FechaSalida>='2017-03-10 00:00:00.000' AND D.FechaLlegada<='2017-03-11 00:00:00.000'
GROUP BY
D.NumOperador;
GO]
Time
If you just want to join hrs and mns together in the result, concatenate both of them :
SELECT
D.numOperador,
( cast ( SUM(DATEDIFF(MINUTE, D.FechaSalida, D.FechaLlegada)) / 60 as varchar)
+
cast ( SUM(DATEDIFF(MINUTE, D.FechaSalida, D.FechaLlegada)) % 60 AS varchar ) ) as time
FROM
trkOperadores O
INNER JOIN trfDespacho D ON O.NumOperador = D.numOperador
WHERE
O.cveTipoOperador = 2
AND O.NumOperador = 900200
AND D.FechaSalida>='2017-03-10 00:00:00.000' AND D.FechaLlegada<='2017-03-11 00:00:00.000'
GROUP BY
D.NumOperador;
GO]
I assume that you want something like this.
DECLARE #D1 DATETIME = '20170401'
DECLARE #D2 DATETIME = '20170402 00:05:00'
SELECT RIGHT( '00' + CAST(DATEDIFF(MINUTE, #D1, #D2) /60 AS VARCHAR(2)) , 2) + ':' + RIGHT( '00' + CAST(DATEDIFF(MINUTE, #D1, #D2) % 60 AS VARCHAR(2)) , 2)
-- 24:05
SELECT
D.numOperador,
SUM(DATEDIFF(MINUTE, D.FechaSalida, D.FechaLlegada)) / 60 AS [Horas] ,
SUM(DATEDIFF(MINUTE, D.FechaSalida, D.FechaLlegada)) % 60 AS [Minutos]
CONVERT(VARCHAR(10),CAST(CAST (D.FechaSalida AS FLOAT) - CAST (D.FechaLlegada AS FLOAT) / 86400. AS DATETIME),108) --86400 equal 1 day
FROM
trkOperadores O INNER JOIN trfDespacho D
ON O.NumOperador = D.numOperador
WHERE
O.cveTipoOperador = 2
AND O.NumOperador = 900200
AND D.FechaSalida>='2017-03-10 00:00:00.000' AND D.FechaLlegada<='2017-03-11 00:00:00.000'
GROUP BY
D.NumOperador;
GO