I have a column which is a sum of total minutes users spend on a task. This column was got using:
(sum(cast(LTRIM(DATEDIFF(SECOND, 0, TotalTimeOtherTasks))as int)) over (partition by headLogs.operatorID)/60) as TotalTimeOtherTasks
This returns e.g 315.
TotalTimeOtherTasks is a column of times for that task e.g
00:30:23
01:05:55
I want to make this show in HH:mm format so, 315 = 05:15.
I've tried doing other answers for similar questions such as; using separate formulas and concatenating them but i get errors such as " '05:15' cannot be converted to an int " once it gets the answer or "':' is not recognized as part of the formula". If i convert it I then can't use sum(). So i think this might be its own question.
One method is to compute the minutes and seconds separately, and then concatenante them
concat(
sum(datediff(second, 0, TotalTimeOtherTasks))
over (partition by headLogs.operatorID) / 60,
':',
sum(datediff(second, 0, TotalTimeOtherTasks))
over (partition by headLogs.operatorID) % 60
) as TotalTimeOtherTasks
Note that I removed the casting, that seems unnecessary here: in most databases, datediff() returns a integer already.
Though the answer is already accepted, I will post my solutions which is working in MySQL.
Reference from here: Convert number of minutes to hh:mm
Assuming the following table structure
create table total_minutes(
id bigint(20) NOT NULL AUTO_INCREMENT,
total_time int,
primary key(id)
);
SELECT total_time, floor(total_time/60) as hours, lpad(floor(total_time%60), 2, '0') as minutes,
concat(floor(total_time/60), ":", lpad(floor(total_time%60), 2, '0')) as hh_mm FROM classifiedads.total_minutes;
Gives
t h m hh:mm
35 0 35 0:35
95 1 35 1:35
69 1 9 1:09
Related
I am creating a SQL report for someone in which exists a column called Labour Hours of Engineer. In the column, the answers are shown as "3H 30M".
I want to change it to decimal. For example, "3H 30M" becomes 3.5.
Or another example is if an engineer works for 23 minutes, in the column, the answer should be 0.38 (rounded to 2 decimal places). 0.38 is the answer when you divide 23 mins by 60.
My current Formula is:
CONVERT(VARCHAR(40), CAST(Labour AS INT)%(24*60)/60) + '.' + CONVERT(VARCHAR(40), CAST(Labour AS INT)%60)
Any way to achieve this, please share.
Assuming that the 'H' and 'M' are always there, one method would be some use of CHARINDEX to find the 'H' and return the "first" characters and also strip those first characters. For minutes, you can just use simple division to get the decimal value
DECLARE #Time varchar(7) = '3H 30M';
SELECT #Time,
CONVERT(int,LEFT(#Time,CHARINDEX('H',#Time)-1)) + (CONVERT(decimal(2,0),REPLACE(STUFF(#Time,1,CHARINDEX('H',#Time),''),'M',''))/60);
This code will cover Hour minute or only minute
select Convert(decimal(26,2),
IIF(Labour like '%H%',(Convert(int, substring(Labour,0,(CHARINDEX('H',Labour)))) * 60 )+IIF(Labour like '%M%',Convert(int, substring(Labour,CHARINDEX('H',Labour)+1,CHARINDEX('M',Labour)-CHARINDEX('H',Labour)-1)),0)
,IIF(Labour like '%M%',Convert(int, substring(Labour,0,CHARINDEX('M',Labour))),0)) /60.00)
I have a table with 2 rows of time intervals. The data is stored as a varchar containing the hour and minutes, like the sample data below. I need to find a way to subtract the first column of data from the second and keep it as a time interval format. As seen below in the following table, I want to subtract colB from colA, to get the numbers in desiredOutcome displayed in the same format.
colA
colB
desiredOutcome
10:30
1:30
9:00
1:50
1:47
0:03
20:10
15:15
4:55
250:10
50:05
200:05
Any and all help is greatly appreciated
EDIT:
To clarify, these are time intervals, not times of the day. I have added more data to the table to show this, it is the amount of time taken in hours and minutes to perform a task. Also, the data is stored in varchar, but I can just use CAST() to change that.
Will say would have recommended storing this as simple minutes using a data type like int, then format for the user to your HH:MM format. It would make calculations like this a lot easier.
So for example instead of storing 250:10, would have stored it as 15010 minutes
Below I converted your HH:MM time lengths to minutes, did the calculation, and then formatted it back again.
Calculating Difference Between HH:MM Time Lengths
DROP TABLE IF EXISTS #Interval
CREATE TABLE #Interval (ID INT IDENTITY(1,1) PRIMARY KEY, colA Varchar(10),colB Varchar(10))
INSERT INTO #Interval
VALUES
('10:30','1:30')
,('1:50','1:47')
,('20:10','15:15')
,('250:10','50:05')
SELECT *
,DesiredOutcome = CONCAT(FLOOR(DeltaInMinutes/60.0),':',FORMAT(DeltaInMinutes % 60,'0#'))
FROM #Interval AS A
/*Find the colons*/
CROSS APPLY (
SELECT idxA = NULLIF(CHARINDEX(':',A.ColA),0)
,idxB = NULLIF(CHARINDEX(':',A.ColB),0)
) AS B
/*Break up into hours and minutes*/
CROSS APPLY(
SELECT HrsA = ISNULL(SUBSTRING(A.ColA,0,idxA),0)
,HrsB = ISNULL(SUBSTRING(A.ColB,0,idxB),0)
,MinutesA = ISNULL(SUBSTRING(A.ColA,idxA+1,100),0)
,MinutesB = ISNULL(SUBSTRING(A.ColB,idxB+1,100),0)
) AS C
/*Find total duration in minutes*/
CROSS APPLY (
SELECT TotalMinutesA = (HrsA * 60) + MinutesA
,TotalMinutesB = (HrsB * 60) + MinutesB
) AS D
/*Calculate delta*/
CROSS APPLY (
SELECT DeltaInMinutes = TotalMinutesA - TotalMinutesB
) AS E
I'm having an issue where I am running a script against a database to get the average difference between multiple VARCHARs that need to be converted to DateTimes, and then take the average between all the results.
My code is:
SELECT YEAR(b.DateAcknow),AVG(datediff(dd,convert(datetime,b.DateAssign),
convert(datetime,b.DateResolv))) as DayAverage,
AVG(datediff(hh,convert(datetime,b.TimeAcknow),
convert(datetime,b.TimeResolv))) as HourAverage
FROM table AS b
WHERE (x = y)
AND YEAR(DateResolv) >= 2006
AND YEAR(DateResolv) < 2016
AND b.resolution <>''
GROUP BY YEAR(b.DateAcknow)
ORDER BY YEAR(b.DateAcknow)`
The result I'm getting does not seem to make sense, much less it includes 1900 which falls outside of my parameters of the where clause
Here it is:
NULL 42 NULL
1900 0 12
2006 7 -5
2007 6 1
2008 7 1
2009 4 1
2010 2 0
2011 2 0
2012 2 0
2013 2 0
2014 2 0
2015 2 0
Am I converting the VARCHARs wrong?
I doubt that the average for thousands of entries from 2010-2015 are all the same 2 days and 0 hours too, so either I'm doing something wrong or the data is bad.
You are filtering by DateResolv and group by DateAcknow.
Filter and group by the same Field and NULL and values outside of the Range should disappear.
You'll probably want to take away the aggregate part and just run:
SELECT YEAR(b.DateAcknow)
, convert(datetime,b.DateAssign) AS DateAssignDateTime
, convert(datetime,b.DateResolv) AS DateResolveDateTime
, datediff(dd,convert(datetime,b.DateAssign), convert(datetime,b.DateResolv)) AS AssignResolveDayDiff
, convert(datetime,b.TimeAcknow) AS TimeAcknowDateTime
, convert(datetime,b.TimeResolv) AS TimeResolveDateTime
, datediff(hh,convert(datetime,b.TimeAcknow), convert(datetime,b.TimeResolv)) AS AcknowResolveHourDiff
FROM table AS b
WHERE (x = y)
AND YEAR(DateAcknow) >= 2006
AND YEAR(DateAcknow) < 2016
AND b.resolution <>''
ORDER BY YEAR(b.DateAcknow)
To ensure that all of your conversions are making sense first. Then you will have a better understanding of what it is you're actually averaging.
Afterwards, if it all checks out, then your query should work fine (though, do check that mxix' change from
...
AND YEAR(DateResolv) >= 2006
AND YEAR(DateResolv) < 2016
...
to
...
AND YEAR(b.DateAcknow) >= 2006
AND YEAR(b.DateAcknow) < 2016
...
makes sense for you.
If you're looking to increase the precision of the output, then try converting your datediffs like so:
Old: AVG(datediff(dd,convert(datetime,b.DateAssign), convert(datetime,b.DateResolv)))
New: AVG(Convert(Decimal(10, 5), datediff(dd,convert(datetime,b.DateAssign), convert(datetime,b.DateResolv))))
Your old query is averaging days, rounded to the nearest integer value, giving you values like '2'. This new adjustment will give you answers like "1.51235" days instead.
Since there's 100k records of differences (both plus and minus), there's a good chance the averages will be close to zero if they follow a normal or uniform distribution. Also try:
AVG(Convert(Decimal(10, 5), ABS(datediff(dd,convert(datetime,b.DateAssign), convert(datetime,b.DateResolv)))))
if you want absolute difference instead. If your old data had values "5, -3, 4, -1, 3", then the old method would produce the average of 2, but if you had the "ABS" function working on them, it would change the values to "5, 3, 4, 1, 3" and will move your resulting average in the ++ direction (here, it changes to "3", or "3.2", if you did your decimal conversion too).
My intention is to display for each year what the average response
time is in Days and Hours. – obizues
Assuming:
DateAcknow is a varchar date with an empty timestamp (e.g., "2011/01/15")
TimeAcknow is DateAcknow's corresponding varchar time (e.g., "15:35")
DateResolve is a varchar date with an empty timestamp (e.g., "2011/01/16") which is always greater than or equal to DateAcknow
TimeResolve is DateResolve's corresponding varchar time (e.g., "13:47")
You want to average total hours difference (using the above example, this record's hours difference is 22)
If you need help with your varchar date's format and the convert function, see:
http://msdn.microsoft.com/en-us/library/ms187928.aspx
The following approach should work to achieve your intention:
SELECT YEAR(b.DateAcknow)
, AVG(DateDiff(Day, Convert(datetime, b.DateAcknow) + convert(datetime, b.TimeAcknow), Convert(datetime, b.DateResolv) + Convert(datetime, b.TimeResolve))) AS AvgDaysDifference
, AVG(DateDiff(Hour, Convert(datetime, b.DateAcknow) + convert(datetime, b.TimeAcknow), Convert(datetime, b.DateResolv) + Convert(datetime, b.TimeResolve))) AS AvgHoursDifference
FROM table AS b
WHERE (x = y) AND YEAR(DateAcknow) >= 2006 AND YEAR(DateAcknow) < 2016
AND b.resolution <>''
GROUP BY YEAR(b.DateAcknow)
This should do it if the assumptions about your data and your intention are correct. It is difficult to help when it's not clear.
I have a table with information on resources, basics are:
ID Total Start End Used
----------------------------------------------
1 350 01-01-2012 31-12-2012 80.6%
2 250 01-01-2012 31-12-2012 51.5%
3 3500 01-01-2012 31-07-2013 12.5%
4 350 01-01-2012 31-10-2012 91.0%
Columns are:
Total -- Total number of the resource (Being currency, time, paper etc).
Start -- Start date of resource
End -- End date of resource
Used -- Percentage of the resource used to date
I have to try to work out (or estimate) when the resource will run out at the rate used so far.
I've tried several different ways using the percentage used and the percentage but nothing makes sense, I'm pretty sure there's a simple way to do this that's staring me in the face but I can't find it.
My ideal output would be in text below but I will probably format in the application:
You have used X% of your [resource name] in Y% of the time allotted,
at this rate the resource will run down around [Run Down Date].
Can anyone work out how this can be calculated?
SQL Fiddle to play with
Edit:
To try and make the problem clearer, I'll explain how I would calculate a single date:
For the first line (ID = 1).
Average % per day = Percentage (80.6) / Days between Start and Today (205)
Average % per day = 0.003931707%
% remaining = Percentage (80.6%)
% remaining = 19.4%
Days remaining = Average % per day (0.003931707%) / % remaining (19.4%)
Days remaining = 49.34243176
Project Run Down = Today + Days Remaining (49.34243176)
Project Run Down = 11/09/2012 (11th Sep)
I've tried converting this process into SQL but I can't get it to work.
you can try something like this
declare #res table(
id int identity(1,1)
,total int
,start date
,[end] date
,used float )
insert into #res(total, start , [end], used)
values
(350, '20120101', '20121231', 0.806)
,(250, '20120101', '20121231', 0.515)
select
*
,used/DATEDIFF(DAY,start,GETDATE()) as avUsePerDay
,1/(used/DATEDIFF(DAY,start,GETDATE())) as expectedDaysTotal
,DATEADD(day,1/(used/DATEDIFF(DAY,start,GETDATE())),start) as expectedToDie
from #res
That would be...
SELECT DATEDIFF(d, [StartDate], GETDATE()) * 100.0 / DATEDIFF(d, [StartDate], [EndDate]) AS PercentageTimeGone,
DATEADD(d, (100 - USED) / (Used / DATEDIFF(d, [StartDate], GETDATE())), GETDATE()) AS ProjectedEndingDate
FROM Resources
What's about
select id, total, start, end, datediff(day,start,getdate()) / ( total / 100 )
I am not good in calculating, but in numbers it's working.
all the best
I am trying to group some records into 5-, 15-, 30- and 60-minute intervals:
SELECT AVG(value) as "AvgValue",
sample_date/(5*60) as "TimeFive"
FROM DATA
WHERE id = 123 AND sample_date >= 3/21/2012
i want to run several queries, each would group my average values into the desired time increments. So the 5-min query would return results like this:
AvgValue TimeFive
6.90 1995-01-01 00:05:00
7.15 1995-01-01 00:10:00
8.25 1995-01-01 00:15:00
The 30-min query would result in this:
AvgValue TimeThirty
6.95 1995-01-01 00:30:00
7.40 1995-01-01 01:00:00
The datetime column is in yyyy-mm-dd hh:mm:ss format
I am getting implicit conversion errors of my datetime column. Any help is much appreciated!
Using
datediff(minute, '1990-01-01T00:00:00', yourDatetime)
will give you the number of minutes since 1990-1-1 (you can use the desired base date).
Then you can divide by 5, 15, 30 or 60, and group by the result of this division.
I've cheked it will be evaluated as an integer division, so you'll get an integer number you can use to group by.
i.e.
group by datediff(minute, '1990-01-01T00:00:00', yourDatetime) /5
UPDATE As the original question was edited to require the data to be shown in date-time format after the grouping, I've added this simple query that will do what the OP wants:
-- This convert the period to date-time format
SELECT
-- note the 5, the "minute", and the starting point to convert the
-- period back to original time
DATEADD(minute, AP.FiveMinutesPeriod * 5, '2010-01-01T00:00:00') AS Period,
AP.AvgValue
FROM
-- this groups by the period and gets the average
(SELECT
P.FiveMinutesPeriod,
AVG(P.Value) AS AvgValue
FROM
-- This calculates the period (five minutes in this instance)
(SELECT
-- note the division by 5 and the "minute" to build the 5 minute periods
-- the '2010-01-01T00:00:00' is the starting point for the periods
datediff(minute, '2010-01-01T00:00:00', T.Time)/5 AS FiveMinutesPeriod,
T.Value
FROM Test T) AS P
GROUP BY P.FiveMinutesPeriod) AP
NOTE: I've divided this in 3 subqueries for clarity. You should read it from inside out. It could, of course, be written as a single, compact query
NOTE: if you change the period and the starting date-time you can get any interval you need, like weeks starting from a given day, or whatever you can need
If you want to generate test data for this query use this:
CREATE TABLE Test
( Id INT IDENTITY PRIMARY KEY,
Time DATETIME,
Value FLOAT)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:00:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:03:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:04:45', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:07:21', 20)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:10:25', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:11:22', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:14:47', 30)
The result of executing the query is this:
Period AvgValue
2012-03-22 00:00:00.000 10
2012-03-22 00:05:00.000 20
2012-03-22 00:10:00.000 30
Building on #JotaBe's answer (to which I cannot comment on--otherwise I would), you could also try something like this which would not require a subquery.
SELECT
AVG(value) AS 'AvgValue',
-- Add the rounded seconds back onto epoch to get rounded time
DATEADD(
MINUTE,
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30) * 30,
'1990-01-01T00:00:00'
) AS 'TimeThirty'
FROM YourTable
-- WHERE your_date > some max lookback period
GROUP BY
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30)
This change removes temp tables and subqueries. It uses the same core logic for grouping by 30 minute intervals but, when presenting the data back as part of the result I'm just reversing the interval calculation to get the rounded date & time.
So, in case you googled this, but you need to do it in mysql, which was my case:
In MySQL you can do
GROUP BY
CONCAT(
DATE_FORMAT(`timestamp`,'%m-%d-%Y %H:'),
FLOOR(DATE_FORMAT(`timestamp`,'%i')/5)*5
)
In the new SQL Server 2022, you can use DATE_BUCKET, this rounds it down to the nearest interval specified.
SELECT
DATE_BUCKET(minute, 5, d.sample_date) AS TimeFive,
AVG(d.value) AS AvgValue
FROM DATA d
WHERE d.id = 123
AND d.sample_date >= '20121203'
GROUP BY
DATE_BUCKET(minute, 5, d.sample_date);
You can use the following statement, this removed the second component and calculates the number of minutes away from the five minute mark and uses this to round down to the time block. This is ideal if you want to change your window, you can simply change the mod value.
select dateadd(minute, - datepart(minute, [YOURDATE]) % 5, dateadd(minute, datediff(minute, 0, [YOURDATE]), 0)) as [TimeBlock]
This will help exactly what you want
replace dt - your datetime c - call field astro_transit1 - your table 300 refer 5 min so add 300 each time for time gap increase
SELECT FROM_UNIXTIME( 300 * ROUND( UNIX_TIMESTAMP( r.dt ) /300 ) ) AS 5datetime, ( SELECT r.c FROM astro_transit1 ra WHERE ra.dt = r.dt ORDER BY ra.dt DESC LIMIT 1 ) AS first_val FROM astro_transit1 r GROUP BY UNIX_TIMESTAMP( r.dt ) DIV 300 LIMIT 0 , 30