sql addtime usage to increment time field - mysql

I am trying to use a variable to increment a time variable used in a stored sql procedure.
I have tried
v_start1 = addtime(v_start1, v_inc);
where:
declare v_start1 Time;
declare v_inc time; or declare v_inc varchar(10);
select start1 from table into v_start1;
select inc from another_table into v_inc;
and it fails to increment v_start1
If I use v_start1 = addtime(v_start1, '00:15:00') it works but 00:15:00 is a fixed value that needs to be changed
How do I go about using a second variable to supply the value to increment v_strar1 by
How do I convert varchar to time; the value may be in the form +00:15 as a string

Are the values coming from "another_table" strings like "+00:15" or Time data type values? This may be a problem.
I would recommend that you avoid using strings and only deal with them as either time or datetime data types. If you have a string like "+15:00" it may mean 15 minutes but it looks to some people like 15 hrs. Maybe in your query the value in the table is a string and is not getting converted correctly. Get it into the table as a Time field and it should work.
As a side note I like to work with a full DATETIME data type rather than Time types like you are doing when I have the need to add/subtract. If you are really only interested in Time, then just use the current day-month-year with your incoming time.
I am not 100% sure for MySql, but for SqlServer and Oracle it is possible to run into the following scenario:
If v_start1 is 23:55:00 and you add 15 minutes it actually becomes 00:00:10 of the next day. If you add 1455 minutes you get the exact same time but 2 days later. So, just looking at Time can get you in trouble.
If you deal with a DATETIME type then you can always use DATE_ADD and add whatever seconds, minutes, etc. easily.

Related

MySQL 5.6 calculation with datatype time within function returns wrong value - but outside is ok

I use mySQL 5.6 on Windows 7 Pro x64 and have the following problem.
SELECT fee(100, '12:00:00');
returns 500,000 which is obviously not correct.
But
SELECT 100 * '12:00:00'/24;
returns the correct result which is 50.
DROP FUNCTION IF EXISTS fee;
DELIMITER //
CREATE FUNCTION fee(price INT, duration TIME)
RETURNS DECIMAL(15,2)
BEGIN
RETURN price * duration/24;
END //
DELIMITER ;
Have you ever encountered this problem? What is the reason behind it?
Thanks for any hints for solving this.
My guess is that in 100 * '12:00:00'/24 expression '12:00:00' is evaluated as string, not as a time expression, and in '12:00:00'/24 operation the string is converted to a number, so it is executed as 12/24, which gives the expected result.
However, when the fee() function is called, '12:00:00' is passed to a parameter with TIME data type. In the duration/24 operation duration is converted to integer first, then the division is executed. However, select cast(cast('12:00:00' as time) as integer) conversion yields 120000, not 12. 120000/24*100=500000 - this is the output received from the original function. According to mysql documentation on TIME:
Be careful about assigning abbreviated values to a TIME column. MySQL
interprets abbreviated TIME values with colons as time of the day.
That is, '11:12' means '11:12:00', not '00:11:12'. MySQL interprets
abbreviated values without colons using the assumption that the two
rightmost digits represent seconds (that is, as elapsed time rather
than as time of day). For example, you might think of '1112' and 1112
as meaning '11:12:00' (12 minutes after 11 o'clock), but MySQL
interprets them as '00:11:12' (11 minutes, 12 seconds). Similarly,
'12' and 12 are interpreted as '00:00:12'.
Although the documentation describes integer to time conversion, it is safe to assume that time to integer conversion works the same way. I would use price * time_to_sec(duration)/86400 to get the right result.
Thank you all for your helps and comments.
#Shadow, #B98 – you are right. The problem has to do with converting '12:00:00' to its corresponding numeric value.
I searched a lot about how MySQL performs converting time to number in general, however I didn't find anything.
So I started a little bit experimenting on it and this is what I found out about it yet:
The default datatype in MySQL is VARCHAR, so every value/"variable" which has no explicit datatype its datatype is VARCHAR(length of value/variable) as you've correctly guessed, Shadow.
Converting VARCHAR to a numeric datatype works generally like this: take all digits from the left of the string up to the point you find a character except 0-9. If immediately after the digits there is a dot “.”, take the dot as the decimal point and continue searching for decimal digits till the string ends or you find a character except 0-9.
So in short: take from the left of the string what matches the pattern [0-9][.[0-9]] and throw the rest of it away – as you mentioned it, B98. Examples: '12:30:59' = 12; '12whatever30whatever59' = 12; '12.30.59' = 12.30; '12.30whatever' = 12.30
However, converting TIME to a numeric datatype works a little bit different: First remove the colons then convert it to an integer. Exempels: '12:00:00' = 120000; '12:30:59' = 123059
Converting DATETIME to a numeric datatype works the same way as converting TIME to numeric, except here get the dashes in the date part, the space between date and time and the colons in the time part removed and then gets the whole string converted to an integer. Exempels: '2015-12-24 12:59:59' = '20151224125959'
Below you find a query which shows this behavior of MySQL.
DROP VIEW IF EXISTS datetimeTypes;
CREATE VIEW datetimeTypes AS
SELECT
'12:59:00.50' AS timeImplicit,
CAST('12:59:00.50' AS TIME) AS timeExplicit,
'12:59:00.50' / 1 AS timeImplicitDiv,
CAST('12:59:00.50' AS TIME) / 1 AS timeExplicitDiv,
'2015-12-24 12:59:59' AS datetimeImplicit,
CAST('2015-12-24 12:59:59' AS DATETIME) AS datetimeExplicit,
'2015-12-24 12:59:59' / 1 AS datetimeImplicitDiv,
CAST('2015-12-24 12:59:59' AS DATETIME)/1 AS datetimeExplicitDiv;
SHOW FIELDS FROM datetimeTypes;
SELECT * FROM datetimeTypes;

MySQL SEC_TO_TIME gives hh:mm:ss.000000

As said in the caption I am wondering why the SEC_TO_TIME-Function of MySQL gives me that Zeros at the end.
Refering to the docu (http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_sec-to-time) that shouldn't happen (I am using MySQL 5.0.11).
Any Idea why this Zeros appears and how to get rid of them? To much zeros for displaying miliseconds.
Sine the zeros doens't break MySQLs Date-funcions, it's more a "I don't like that"-Question rather than a real Problem (at least till now^^)
// EDIT: I just figured out that the zeros aren't coming from the SEC_TO_TIME but from the FROM_UNIXTIME()-Function. Thx to #Abhik Chakraborty to ask for the input!
// EDIT2: I used FROM_UNIXTIME(last_try, '%Y-%m-%d %H:%i:%s') to get rid of the zeros. But When I do TIME(FROM_UNIXTIME(last_try, '%Y-%m-%d %H:%i:%s')) the zeros are back. Why??
Seems like every function adds the zeros back. Using SEC_TO_TIME on a simple integer-value also gives zeros...
Here is the whole query iam using:
SELECT
SEC_TO_TIME(FLOOR(TIME_TO_SEC((TIME(FROM_UNIXTIME(`last_try`))))/1800)*1800)
FROM `last48h`
The query reads the timestamp, gets only the time, converts it to seconds, breaks the seconds into half-hours (/1800 gives 0 < x < 48) rounds down and converts back to time
SEC_TO_TIME produces a TIME data type for its result. You can format that as you wish with DATE_FORMAT.
If you actually need subsecond time resolution you'll need to move to version 5.6.4 or beyond.
When you directly SELECT any sort of TIME data type to display, you get a default TIME-to-string conversion operation. The default TIME-to-string conversion in some generations of MySQL yields a string ending in hh:mm:ss+zz00. +zz00 is a timezone indicator, and often displays as +0000. Any chance that's what you're seeing?
It doesn't make sense to try to handle a UNIX_TIMESTAMP() style number of seconds using SEC_TO_TIME(). As of mid-2014 the current unix timestamp value is above 1.39 gigaseconds. TIME data types are used for stuff like elapsed times, and have a limit of just under 839 hours (3 megaseconds, precisely 3020399 seconds), and silently truncate their values.
For example, this is a good use of SEC_TO_TIME:
SELECT SEC_TO_TIME(end_timestamp - start_timestamp) AS duration
edit
Strangely enough, this query
SELECT
SEC_TO_TIME(FLOOR(TIME_TO_SEC((TIME(FROM_UNIXTIME(UNIX_TIMESTAMP()))))/1800)*1800) AS a,
FLOOR(TIME_TO_SEC((TIME(FROM_UNIXTIME(UNIX_TIMESTAMP()))))/1800)*1800 AS b,
TIME_TO_SEC((TIME(FROM_UNIXTIME(UNIX_TIMESTAMP()))))/1800 AS c,
FROM_UNIXTIME(UNIX_TIMESTAMP()) AS d,
FROM_UNIXTIME(UNIX_TIMESTAMP() - UNIX_TIMESTAMP() % 1800) as e
doesn't show any of the 0000 stuff through the phpmyadmin instance I use.
By the way, most people who round time to the nearest interval (a half-hour in your case) prefer to use a modulo and a subtraction; it's less dependent on implicit numerical type conversion than your method.
SELECT TIME(FROM_UNIXTIME(last_try - last_try%1800))
does what the query in your question does.
I had the same problem with the 'SEC_TO_TIME' function.
I had overlooked the fact that I was storing timestamps as a VARCHAR.
I changed my datatypes from VARCHAR to BIGINT and it is formatting the output values as expected (hh:mm:ss).
Try to use TIME_FORMAT with %k specifier it should help.

UNIX_TIMESTAMP outputting NULL in MySQL?

I've got a table setup which has populated data. In column "date", I have dates in the following format:
yyyymmdd i.e. 20131110
I have created a new field and called it newdate with the text format.
Then, I open up the SQL window and put the following in
UPDATE wl_daily
SET
newdate = UNIX_TIMESTAMP(date)
For some reason, it is running correctly, however it only outputs NULL to all the rows. Also, the column name is blank for some reason
Any suggestions?
That's because your field in a string and you're trying to add timestamp to it which is not a string. You need to use a valid datetime field like timestamp for this to work.
Advice: don't store dates and times as strings. Store them in their native format. It makes working with dates and times much easier.
While John Cronde's answer is correct - it doesnt help your situtation
UNIX_TIMESTAMP(STR_TO_DATE(`date`, '%Y%m%d'))
will do the conversion for example
SELECT UNIX_TIMESTAMP(STR_TO_DATE('20131111', '%Y%m%d'))
returns
unix_timestamp(STR_TO_DATE('20131111', '%Y%m%d'))
---------------------------------------------------
1384128000
You should only use this to convert your columns to the date specific columns. Converting each time you need a number will add load and slow down the query if used in production

MySql - Bad format for Time 'hhh:mm:ss' in column x

In MySQL, I am trying to get difference between two timestamp value and storing the result in time column. But sometimes the result comes in 'hhh:mm:ss' format. While trying to access that column in Java using Result.getTime(), it is throwing error saying 'Bad format for time in column x'.
To get better idea, store the result of following query in time column and try to access this value in Java.
SELECT SEC_TO_TIME(ABS(TIMESTAMPDIFF(SECOND,'2013-01-26 19:03:48','2013-02-15 06:59:36'))) as 'RESULT';
What should I do to get result even if it has 'hhh:mm:ss' format (without any error)?
Thanks in advance.
I assume you run query and result set contain the result
String hourMinSec=resultset.getString("RESULT");
String[]result=hourMinSec.split(":");
int hour=Integer.parseInt(result[0]);
int min=Integer.parseInt(result[1]);
int second=Integer.parseInt(result[2]);
Expressing difference between two dates as date is meaningless i think. Just to answer your question if you want to create time you can use following
Time time =new Time(hour, min, second);
But i feel its meaningless.
You can't express the difference between two dates as another date. For example if you will got 31 days difference you can't say if it is 1 month or 1 month and 1 day.
You should create your own object to storage this data.

why this MySQL SELECT doesn't include the right dates?

The main problem is, that I have stored in database datetime , not the date (what I need). Ok never mind.
I have thousands of reports stored each day.
I need to LEFT by 10 my datetime_view (to cut the time) and everything's fine. Except this. I'm trying to figure out why do I have to put in the condition + one day from the future? Otherwise it won't search what I want.
SELECT
LEFT(datetime_view,10),
count(type)
FROM reports
WHERE
type IN (1,2,5)
AND
datetime_view>='2012-10-28'
AND
datetime_view<='2012-11-04'
group by LEFT(datetime_view,10);
You can see I must search from the future. Why??
It gives me an output from 28.10 to 3.11 ....
don't use string operations on date/time values. MySQL has a huge set of functions for date/time manipulation. Try
GROUP BY DATE(datetime_view)
instead, which will extract only the date portion of the datetime field. Your string operation is not y10k compliant. Using the date() function is.
As for your plus one day, consider how the comparisons are done: A plain date value, when used in date/time comparisons, has an implicit 00:00:00 time value attached to it, e.g. all dates have a time of "midnight".
i think it's better to use DATE(datetime_view) to cut the time instead of LEFT(datetime_view,10), also on the where condition:
DATE(datetime_view) <= '2012-11-03'