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')
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
I have tried various recommendations based off of other posts with no avail.
I have a database scheme of records with a Created_Date Key, and Value would be 01/01/2017
I am trying to query the database records to give a returned count of How many records per month and which month those fall in line with.
With the following
SELECT SQL_NO_CACHE MONTH(`Created_Date`), COUNT(*)
FROM `CRM_Leads`
GROUP BY MONTH(`Created_Date`)
I return
MONTH(`Created_Date`) COUNT(*)
NULL 872
I have also tried almost all the variations on the following post
Count records for every month in a year
Any help would be appreciated.
assuming your created_date is a string of format ('dd-mm-yyyy') the you should convert as date with str_to_date
SELECT SQL_NO_CACHE MONTH(str_to_date(`Created_Date`, '%d/%m/%Y')), COUNT(*)
FROM `CRM_Leads`
GROUP BY MONTH(str_to_date(`Created_Date`, '%d/%m/%Y'))
For as long as you store date/time information as strings, you will have great difficulty using any date/time specific functions and features. If you are getting NULL from MONTH(str_to_date(Created_Date, '%d/%m/%Y')) then the str_to_date isn't converting the strings to dates and the most likely reason for this is the d m y "pattern" is not corrrect.
All you have old us about your "strings that might be dates" is that one of them looks like this: 01/01/2017. Now that could be DD/MM/YYYY or MM/DD/YYYY and we simply cannot tell which one is correct from the single value you have chosen to share with us. Look for any day value greater then 12 in your data e.g. 17/01/2017 ==> DD/MM/YYYY or 01/17/2017 ==> MM/DD/YYYY
Once you have made the choice of which pattern your "strings that might be dates" follow; apply that pattern in the str_to_date() function. You migh want to try a few different patterns to get the best one (and these are just 3 of many you could try):
# which pattern is best for you?
SELECT Created_Date
, str_to_date(`Created_Date`, '%d/%m/%Y') "d/m/y"
, str_to_date(`Created_Date`, '%m/%d/%Y') "m/d/y"
, str_to_date(`Created_Date`, '%Y-%m-%d') "y-m-d"
FROM `CRM_Leads`
You will not have success with your group by query until you choose the most appropriate d m y pattern to apply in teh str_to_date function. Note here that you might also have a variety of patterns in your data, in which case you have an even bigger problem to solve.
Once you have made the choice of which pattern your "strings that might be dates" follow; apply that pattern in the str_to_date() function and ONLY THEN your group by query will work.
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
Lets say I have a table that contains the following - id and date (just to keep things simple).
It contains numerous rows.
What would my select query look like to get the average TIME for those rows?
Thanks,
Disclaimer: There may be a much better way to do this.
Notes:
You can't use the AVG() function against a DATETIME/TIME
I am casting DATETIME to DECIMAL( 18, 6 ) which appears to yield a reasonably (+- few milliseconds) precise result.
#1 - Average Date
SELECT
CAST( AVG( CAST( TimeOfInterest AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
#2 - Average Time - Remove Date Portion, Cast, and then Average
SELECT
CAST( AVG( CAST( TimeOfInterest - CAST( TimeOfInterest AS DATE ) AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
The second example subtracts the date portion of the DATETIME from itself, leaving only the time portion, which is then cast to a decimal for averaging, and back to a DATETIME for formatting. You would need to strip out the date portion (it's meaningless) and the time portion should represent the average time in the set.
SELECT CAST(AVG(CAST(ReadingDate AS real) - FLOOR(CAST(ReadingDate as real))) AS datetime)
FROM Rbh
I know that, in at least some of the SQL standards, the value expression (the argument to the AVG() function) isn't allowed to be a datetime value or a string value. I haven't read all the SQL standards, but I'd be surprised if that restriction had loosened over the years.
In part, that's because "average" (or arithmetic mean) of 'n' values is defined to be the sum of the values divided by the 'n'. And the expression '01-Jan-2012 08:00' + '03-Mar-2012 07:53' doesn't make any sense. Neither does '01-Jan-2012 08:00' / 3.
Microsoft products have a history of playing fast and loose with SQL by exposing the internal representation of their date and time data types. Dennis Ritchie would have called this "an unwarranted chumminess with the implementation."
In earlier versions of Microsoft Access (and maybe in current versions, too), you could multiply the date '01-Jan-2012' by the date '03-Mar-2012' and get an actual return value, presumably in units of square dates.
If your dbms supports the "interval" data type, then taking the average is straightforward, and does what you'd expect. (SQL Server doesn't support interval data types.)
create table test (
n interval hour to minute
);
insert into test values
('1:00'),
('1:30'),
('2:00');
select avg(n)
from test;
avg (interval)
--
01:30:00
I'm using a MySQL query to pull a range of datetimes as a Unix Timestamp (because I'll be converting them to Javascript time). I'm grouping by 'FROM_UNIXTIME' as below:
SELECT
UNIX_TIMESTAMP(DateAndTime) as x,
Sum(If(Pass='Pass',1,0)) AS y,
Sum(If(Pass='Fail',1,0)) AS z,
Sum(If(Pass='Fail',1,0))/(Sum(If(Pass='Pass',1,0))+Sum(If(Pass='Fail',1,0))) AS a,
cases.primaryApp
FROM casehistory, cases
WHERE DATE_SUB(CURDATE(),INTERVAL 80 DAY) <= DateAndTime
AND cases.caseNumber = casehistory.caseNumber
AND cases.primaryApp = 'Promo'
GROUP BY FROM_UNIXTIME(x, '%Y-%m-%d')
While I'd expected my timestamps to be returnd evenly spaced (that is, same amount of time between each day/group), I get the following series:
1300488140, 1300501520,
1300625099, 1300699980
All the other data from the query is correct, but because the spacing of the timestamps is irregular, a bar chart based on these stamps looks pretty awful. Perhaps I'm doing something wrong in the way I apply the grouping?
Thank you for the reply. My query 'made sense' in that it produced that could be plotted (the grouping was done on the x alias for the dateandtime value), but the problem was that pulling a Unix timestamp from the database and grouping by day returned a series of timestamps that did not have equal distance between them.
I solved this by pulling only the day (without the time) from the datetime MySQL field, then - in PHP - concatenating an empty time to the date, converting the resulting string to a time, then multiplying the whole shebang by 1000 to return the Javascript time I needed for the charting, like this:
x = x . ' 00:00:00';
x = strtotime(x) * 1000;
The answer put me on the right track; I'll accept it. My chart looks perfect now.
Question is very confused.
Your SQL statement makes no sense - you are grouping by entities not found in the select statement. And a bar chart plots an ordered set of values - so if there's something funny with the spacing then its not really a bar chart.
But I think the answer you are looking for is:
SELECT DATE_FORMAT(dateandtime, '%Y-%m-%d') as ondate
, SUM(IF(Pass='Pass',1,0)) AS passed
, SUM(IF(Pass='Fail',1,0)) AS failed
, SUM(IF(Pass='Fail',1,0))
/(SUM(IF(pass='Pass',1,0))+SUM(IF(Pass='Fail',1,0))) AS fail_pct
, cases.primaryapp
FROM casehistory, cases
WHERE DATE_SUB(CURDATE(),INTERVAL 80 DAY) <= dateandtime
AND cases.casenumber = casehistory.casenumber
AND cases.primaryapp = 'Promo'
GROUP BY DATE_FORMAT(dateandtime, '%Y-%m-%d')
ORDER BY 1;
And if you need Unix timestamps, wrap the above in....
SELECT UNIX_TIMESTAMP(STR_TO_DATE(CONCAT(ilv.ondate, ' 00:00:00'))) AS tstamp
, passed
, failed
, fail_pct
, primaryapp
FROM (
...
) AS ilv
Note that you'll still get anomolies around DST switches.
C.