How to make custom rounding function in my situation? - ms-access

I have a table that has 4 time fields Time1 to Time4 and after that, I have another field that calculates total hours by subtracting Time4 - Time1 = Real Hours.
After that calculation, I want to make a rounding every number by 30 minutes, for example:
2:30 should stay as it is.
1:14 I want to round this up to 30 means 1:30.
1:41 I want to round this up to 2 means 2:00.
Minutes below 30 round to 30 except 00, and greater than 30 to 1 hour except 30.
How can I make something like that possible? Is there any built-in ms-access function that can do that?
I hope that I explained well!
My Table & Examples
I've tried this way but not working at all:
Thanks for your help :)

Like this:
Public Function RoundTimeUp( _
ByVal datDate As Date) _
As Date
Const cintMult As Integer = 48 '30 minute round
'Const cintMult As Integer = 96 '15 minute round
'Const cintMult As Integer = 144 '10 minute round
'Const cintMult As Integer = 288 '5 minute round
RoundTimeUp = CDate(-Int(CDec(-datDate * cintMult)) / cintMult)
End Function
Addendum
If numeric values of the time values can be negative, values will appear as being rounded down. To prevent this, use Abs:
EX44Abs: RoundTimeUp(Abs([TimeField]))
Val0341 holds the constant: CDbl(#03:41:00#)
ValStAuf shows the numeric values.
EX44 shows the rounded time without Abs, EX44Abs the rounded time using Abs.

Related

How can I convert this to DATETIME SQL?

Trying to convert this value to DATETIME and unsuccessful so far. Thoughts and ideas are welcome.
03MAR2020:02:45:58.977000
You can use the function STR_TO_DATE() with the proper format:
select str_to_date('03MAR2020:02:45:58.977000', '%d%b%Y:%k:%i:%s.%f')
See the demo.
Result:
2020-03-03 02:45:58.977000
in SQL Server
03MAR2020:02:45:58.977000 is failing to convert tot datetime because, first there is an extra : sign after the year and the fractional seconds is 6 digits instead of max 3.
If the string is always the same length and the same format, then you can use the following to solve this problem:
DECLARE #example varchar(25) = '03MAR2020:02:45:58.977000'
SET #example = LEFT(#example, 22) --- remove last 3 zeros
SET #example = STUFF(#example, CHARINDEX(':', #example), LEN(':'), ' ') ---repalce the first ':'
SELECT convert(datetime, #example) --- convert to datetime
More details: Here are the parts of datetime data type in SQL Server.
YYYY is four digits from 1753 through 9999 that represent a year.
MM is two digits, ranging from 01 to 12, that represent a month in the specified year.
DD is two digits, ranging from 01 to 31 depending on the month, that represent a day of the specified month.
hh is two digits, ranging from 00 to 23, that represent the hour.
mm is two digits, ranging from 00 to 59, that represent the minute.
ss is two digits, ranging from 00 to 59, that represent the second.
n* is zero to three digits, ranging from 0 to 999, that represent the fractional seconds.
Taken from the SQL server documentation
https://learn.microsoft.com/en-us/sql/t-sql/data-types/datetime-transact-sql?view=sql-server-ver15

SQL Query to convert HHMM to minutes

I have a dataset that includes time columns in integer format as HHMM (i.e., 1730 means 5.30 PM). I would like to calculate the difference in time between rows in terms of minutes.
For example, the difference between 1730 (5.30 PM) and 1315 (1.15 PM) should result in 255 (as there are 4 hours and 15 mins difference)
Is there any way to make some calculations over time values in integer format to convert them to minutes?
So far I have tried the following to convert HHMM integer to minutes:
MOD(a,100) + (a DIV 100 ) * 60
But it does not work with error 'no viable alternative at input'.
Thanks in advance.
I have found a way to convert the number to minutes without changing the integer format. From minutes, you can do any operation between column values like this :
((a % 100) + (FLOOR(a/100)) *60)
Where a is an integer in the HHMM time format.
Hope this is helpful to others.
Best regards.

Explain MySQL Query for "How to group time column into 5 minute intervals"

I found various solution for the problem like here:
How to group time column into 5 minute intervals and max/min value respectively SQL?
https://dba.stackexchange.com/questions/195353/grouping-data-into-5-minute-intervals-within-a-time-range
Grouping into interval of 5 minutes within a time range
The code solving the task looks like:
SELECT
FROM_UNIXTIME((UNIX_TIMESTAMP(table.timestamp) DIV 300) * 300) AS Timestamp,
val AS AgregatedValue
From foo
GROUP BY Timestamp
ORDER BY Timestamp
Can someone explain why the solution provided works?
I couldn't find an answer with a nice description of how it actually works.
Why do you DIV by 300 seconds in the first place and finally multiply by 300 seconds?
What happens in the "background"?
I read the documentation about UNIX_TIMESTAMP(timestamp) which returns the value of the argument as an unsigned integer in seconds since '1970-01-01 00:00:00' UTC.
I know that FROM_UNIXTIME()happens to be the reverse function of UNIX_TIMESTAMP(timestamp)
Maybe this question is stupid, however I am stuck.
The answer is in the token DIV.
DIV is not only dividing (/), but also casting to integer implicitly.
You do this to get an integer number without remainder. Basically, this is the same as using an explicit cast after dividing, or using ROUND() or FLOOR() after dividing.
Ref:
https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html
Integer division. Discards from the division result any fractional
part to the right of the decimal point.
UNIX_TIMESTAMP(table.timestamp) contain a date stored as the the number of second strating from 1970-01-01 00:00:00' UTC.
in 5 minutes you have 300 second
so the UNIX_TIMESTAMP(table.timestamp) by 300 return the number of part you have in number for each 300..
this integer part is a number that multipied by 300
UNIX_TIMESTAMP(table.timestamp) DIV 300) * 300
return a each number of seconds for each 5 minutes
the last conversion
FROM_UNIXTIME((UNIX_TIMESTAMP(table.timestamp) DIV 300) * 300)
return the date and is used for group by
SELECT
FROM_UNIXTIME((UNIX_TIMESTAMP(table.timestamp) DIV 300) * 300) AS Timestamp,
val AS AgregatedValue
From foo
GROUP BY Timestamp
ORDER BY Timestamp

Calculating the tendency of a value over time

I've got a table with (amongst other values) the temperature for the last 4 hours. When making a graph of it I can see the 'tendency' of the graph on an eye blink:
The thick red line obviously has a negative direction. While the green line has a positive direction.
How can I calculate this 'direction' value of the last 3 hours worth of data. This data can be retreived from the database with the following sql-statement:
SELECT temp FROM weather WHERE time_utc => NOW() - INTERVAL 3 HOUR
Is there a function like AVG() or something to calculate this or am I overthinking this?
What about this :
SELECT HOUR(time_utc) as hour_group, AVG(temp)
FROM weather
WHERE time_utc => NOW() - INTERVAL 3 HOUR
GROUP BY hour_group
This way you divide your measures in hour block and can compare the first with the last?

What instead of CONVERT(TIME, x) Datepart?

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