I created a field called 'hours_spent' in MySQL using the decimal datatype to store time. The values are stored like this 1.30, 2.30 etc... (for 1hr30min, 2hr30min).
I want to calculate the sum of various time values.
The sum of time is not what I expected: 1.30 + 2.30 = 3.60, whereas I expected 4.00.
I used the SUM function in MySQL to count the hours_spent field. If the values are 0.30 + 1.50 = 1.80, whereas I expected 2.20.
My first mistake was to use the decimal type instead of the time datatype, but I cannot change datatype.
So, is there any way to sum the time values and get result as I expect?
Thanks
I prepared you a demo at sqlfiddle, you can try it there if you want:
http://www.sqlfiddle.com/#!2/c9afc/2
Here are the query samples:
select #indexer:=instr(dateasdecimal, '.')
, left(dateasdecimal, #indexer-1) * 60 + substr(dateasdecimal, #indexer+1) as totalMinutes
from testtable;
select #indexer:=instr(dateasdecimal, '.')
, sum(left(dateasdecimal, #indexer-1) * 60 + substr(dateasdecimal, #indexer+1)) as totalMinutes
from testtable;
Note: Please don't forget to accept answers to your questions:
https://meta.stackexchange.com/a/65088/200585
To convert a decimal into seconds, you could use this:
truncate(hours_spent,0)*60+(hours_spent-truncate(hours_spent,0))*100
and then you can do the sums easily. Then you can convert back seconds to the decimal format with this:
truncate(seconds/60,0)+truncate(mod(seconds, 60)/100,2)
You could always turn the decimals into a string, cast as time, then sum that time using time_to_sec and produce a formatted time with sec_to_time. Of course, it would be much better to be storing those times a different way, even if it involves converting the entire dataset.
SELECT sec_to_time(sum(time_to_sec(goodTime))) FROM (
SELECT CAST(badTime AS TIME) AS goodTime FROM (
SELECT REPLACE(badTime, '.', ':') AS badTime FROM (
SELECT CAST(badTime AS dec(4,2)) AS badTime FROM (
SELECT 1.3 AS badTime
UNION select 2.3
) z
) y
) x
) w
Related
As title, I'm trying to convert a VARCHAR column in a DATE column, and data is populated in that format "DDMMYYYY" ex. XMAS is "25122022" and in this case the correct formula should be STR_TO_DATE(column, '%d%m%Y')Well, when I execute this query I get an error since in some cases I have values with a "missing" char, I mean, for example, "1012023" when the day is <10 the query fails, cause it checks for "01122023" instead.I could solve this easily by adding a 0 to all fields having length 7, but I'd like to make it more clean.Reading better the usage of STR_TO_DATE I noticed that I could replace %d with %e since the second choice should theorically consider days from 0 to 31 instead of 01 to 31.Unexpectedly the query didn't work and gave me the same erorr at the first instance of a length 7 string.Am I doing something wrong?Thanks in advance.
We can try left padding your date string with zero to a length of 8:
WITH yourTable AS (
SELECT '1012023' AS dt
)
SELECT STR_TO_DATE(LPAD(dt, 8, '0'), '%d%m%Y') AS dt_out -- 2023-01-01
FROM yourTable;
Demo
SELECT SUM(render) AS total FROM mytable
This is my code for getting the summation of all rendered hrs. But the output turned out to be like for instance I have 04:30:00 and 03:15:00, then the output turned to 074520, but I want it to be like 7.75 hrs
Here is one way to do it in MySQL:
SELECT
SUM(HOUR(render) * 60.0 + MINUTE(render)) / 60.0 AS TotalHours
FROM mytable
The expression HOUR(render) * 60.0 + MINUTE(render) converts time value into the number of minutes which we sum up to get the total.
You can add SECOND() to the formula to get a more precise answer if you want.
If you want to sum a time type in MySQL, use:
select sum(time_to_sec(render))
from mytable;
This converts the time to a seconds value, sums the value, Then, if you want to convert it back to another format, convert the seconds:
select sum(time_to_sec(render)) / (60 * 60) as decimal_hours,
sec_to_time(sum(time_to_sec(render))) as time_format
MySQL does not directly sum time values. It is going to convert them to a number of the form HHMMSS. So, 00:00:55 is 55. If you add it to itself you get 110, which has nothing to do with 00:01:50.
I am wondering how to express average time formatted like "MM:SS". I have a table typed with text.
myTable1
09:37
10:17
...
If I changed myTable to TIME type, which returns "hour:minute:00", not "MM:SS"
myTable2
09:37:00
10:17:00
So, what I found is
avg(time_format(sec_to_time(round(time_to_sec(TPP)/60, 0)), '%i:%s'))
It returns
myTable3
09:37
10:17
my final goal is averaging those rows
When I use avg() on myTable1,3 it returns '9.5000'
as I expected it returns '09:57'
My questions came from the goal to average myTable1 to be with "MM:SS" formatted
How about adding the hour component and not dividing by 60?
time_format(sec_to_time(avg(time_to_sec(concat('00:', TPP)
)
)
), '%i:%s'
)
The avg() should also be called on the numeric value of seconds, before the conversion back to a time format.
You want to first convert your string to time, then seconds, in order to compute the average. Then convert back to a string with the desired format :
TIME_FORMAT(SEC_TO_TIME(
AVG(TIME_TO_SEC(STR_TO_DATE(TPP, '%h:%i')))
), '%h:%i')
I have a variance report query here I need the 'Variance' to not have 10 decimal points in the Variance Column. What is the most convenient way to round Variance results to the 100th?
WITH A AS
(
select
A.FACTORY,
A.JOB_NUMBER,
A.PROCESS_STAGE,
A.PART_CODE,
B.PART_DESC_1,
A.INPUT_QTY_STD,
A.QUANTITY_INPUT,
A.QUANTITY_OUTSTANDING,
A.INPUT_QTY_ACTUAL,
(A.QUANTITY_OUTSTANDING*100/NULLIF(A.INPUT_QTY_STD,0)) as variance,
A.ACTUAL_CLOSE_DATE
from
(select * from [man_prod].[dbo].[JOB_STAGE_LINES]
where JOB_NUMBER in (select JOB_NUMBER from JOB_OUTPUTS where
BF_QTY_ACTUAL<>0
and ABS(DATEDIFF(HOUR,ACTUAL_CLOSE_DATE,GETDATE())) < 12 and STATUS_FLAG='C'
)) A
join fin_prod.dbo.PRODUCT_MASTER B
ON A.PART_CODE=B.PART_CODE
WHERE
A.INPUT_QTY_STD<>0 and
A.QUANTITY_OUTSTANDING <>0
)
SELECT * FROM A WHERE A.variance >10.000000 OR A.variance <-10
order by PROCESS_STAGE asc ,PART_CODE asc, variance desc ;
The Variance column comes out at 00.0000000000 i need it to display 00.000 or 00.000000
Help is greatly appreciated
Use the MySQL ROUND() function, the second argument is the number of decimal places if it is positive.
ROUND((A.QUANTITY_OUTSTANDING*100/NULLIF(A.INPUT_QTY_STD,0)), 3) as variance,
In this example if the value is 0.0000000000 it would be rounded to 3 decimal places, or 0.000.
You can use the TRUNCATE option:
TRUNCATE((A.QUANTITY_OUTSTANDING*100/NULLIF(A.INPUT_QTY_STD,0)), 3) as variance,
or use the ROUND if you are looking for rounding(as suggested by doublesharp)
ROUND((A.QUANTITY_OUTSTANDING*100/NULLIF(A.INPUT_QTY_STD,0)), 3) as variance,
Using Convert to convert it to a decimal of the desired length is what i prefer when i am not actually rounding the value, just formatting.
CONVERT(DECIMAL(10,3),10000)
I have complicated query over very big table.
Long story short, when I use convert time to select period of day (let's say 12-13h, converting it from datetime row) query takes few minutes, instead of few seconds without convert!
So, I tried datepart, and it works well, almost instant, but, problem is, how to point to hours and minutes in same time?
Any other fast solution is more than welcome.
Thanks.
Meanwhile I came up with this:
DATEPART(HOUR, datetimecolumn)*100 + DATEPART(MINUTE, datetimecolumn)) between 1210 and 1540
You can use datePart if you are willing to do a bit of math, as shown below:
12:10 = 12 * 60 + 10 = 730 minutes
15:40 = 15 * 60 + 40 = 940 minutes
select * .....
where datepart(mi, datefield) between (12*60+10) and (15*60+40)
If you have a constant periods - i.e. - always hourly and no any floating periods - you may introduce something like "ordinal number of period" calculated field, index on it and query of it with precalculated period value
OR
is there are no any constant periods - try to calculate proper begin and end values prior to SELECT statement and use them in the query.
Keep in mind that using functions in where clause of query - sometimes is a bad idea. Using functions in ORDER BY clause - always bad
You can get GETTIME from following Function
alter function GetTimeOnly(#_DateTime DateTime)
returns datetime
as
begin
return dateadd(day, -datediff(day, 0, #_datetime), #_datetime)
end
go
OR YOU CAN HAVE THE TIME FROM CONVERT FUNCTION.
SELECT
CONVERT(VARCHAR(8),GETDATE(),108) AS HourMinuteSecond,
CONVERT(VARCHAR(8),GETDATE(),101) AS DateOnly