MysQL Date and Time Manipulation - mysql

I have a 215 character field, The 16th to the 21st characters are date in the format 030914.
I want to be able to convert that to Date and write it into an adjoining field in the MySQL format yyyy-mm-dd.
I tried String to Date conversion but that is happening only if the date characters are enclosed by 'c' i.e. inverted commas.
Since I have more than 20K records that seems unfeasible.
Characters 22 to 25 is time in the format 1014. This needs to be written into another adjoining field in Time format i.e. hh:mm:ss.
For an experienced MySQL programmer it is a matter of minutes.

QUERY
Fetching Date -
SELECT DATE_FORMAT(
STR_TO_DATE(SUBSTRING(your_column,16,6),"%d%m%y"),
"%Y-%m-%d")
FROM your_table;
Fetching Time-
SELECT DATE_FORMAT(
STR_TO_DATE(SUBSTRING(your_column,22,4),"%h%i"),
"%h:%i:%s")
FROM your_table;
Fetching Both-
SELECT DATE_FORMAT(
STR_TO_DATE(SUBSTRING(your_column,16,10),"%d%m%y%h%i"),
"%Y-%m-%d %h:%i:%s")
FROM your_table;
Here's the demo http://sqlfiddle.com/#!2/ac7e45/10

Related

Get 5 days back records with specific date formate with mysql

I want to select records of 5 days ago with mysql, but the problem is that my date column is varchar and in the following format yyyy-mm-dd 00:00:00 AM/PM.
How can I convert this date format to mysql date and select records from 5 days back?
my date column name is 'date_time'
This is a job for STR_TO_DATE().
Try this.
... WHERE DATE(STR_TO_DATE(date_time,'%Y-%m-%d %h:%i:%s %p')) = CURDATE() - INTERVAL 5 DAY
The '%Y-%m-%d %h:%i:%s %p' DATE_FORMAT() string matches your textual date format.
This will never be fast if you have to search through a large number of rows, because it isn't sargable. It can't exploit an index.

MySql timestamp rounding then reformatting in human readable format

I have the following query from Group OHLC-Stockmarket Data into multiple timeframes - Mysql.
SELECT
FLOOR(MIN(`timestamp`)/"+period+")*"+period+" AS timestamp,
SUM(amount) AS volume,
SUM(price*amount)/sum(amount) AS wavg_price,
SUBSTRING_INDEX(MIN(CONCAT(`timestamp`, '_', price)), '_', -1) AS `open`,
MAX(price) AS high,
MIN(price) AS low,
SUBSTRING_INDEX(MAX(CONCAT(`timestamp`, '_', price)), '_', -1) AS `close`
FROM transactions_history -- this table has 3 columns (timestamp, amount, price)
GROUP BY FLOOR(`timestamp`/"+period+")
ORDER BY timestamp
In my select statement, FLOOR(MIN(timestamp)/"+period+")*"+period+" AS timestamp,
I am trying to understand what it is doing. and
I need to convert this back to a mysql date/time Y-M-D H:i:s string or a UTC timestamp for parsing via javascript.
Let's assume that +period+ is 86400 (The number of seconds in a day)
Let's assume that the timestamp is '2015-12-08 20:58:58'
From what I can see, it takes the timestamp, which internally is stored as an integer and divides by 86400.
'2015-12-08 20:58:58' / 86400 = 233231576.4566898000
It then uses the FLOOR operation which would make it 233231576 then multiplies by 86400 again (I assume that this is to ensure rounding to the day)
I end up with 20151208166400.
So that's the 8th December 2015 but I also have 166400 which I have no idea what it is?
So now the second part of the question is, how to convert this integer to 2015-12-08 %H:%i:%s or even a UTC timestamp for parsing via Javascript.
I mentioned the problem in the comment, but not a fix. The problem is that the proposed code is for a unix timestamp, not a datetime value.
This can be fixed by doing appropriate conversions
SELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(MIN(timestamp)) / $period) * $period)
This gives you the flexibility of have arbitrary numbers of seconds for the groupings.
You're right that FLOOR(timestamp / 86400) * 86400 is a crude way of rounding a UNIX-style timestamp (seconds since 1970-01-01 00:00UTC) to midnight on the present day UTC.
If that's what you're trying to do, I suggest you try this kind of MySQL code:
SELECT DATE_FORMAT(DATE(`timestamp`), '%Y-%m-%d'),
...
GROUP BY DATE(`timestamp`)
This uses MySQL's built in date arithmetic to turn a timestamp into midnight.
But you should be careful of one thing. Those timestamps are all stored in UTC (f/k/a Greenwich Mean Time). When you do date arithmetic with them, or pull them out of the database to use them, they're automatically converted to local time according to your MySQL time zone settings.
It is rounding timestampt to period (e.g day).
DATE_FORMAT( DATE( FLOOR(MIN(timestamp)/"+period+")*"+period+" ) , '%Y-%m-%d %H:%i:%s' )
If period==day consider using only MySQL period rounding by DAY().
Convert a Date object to a string, according to universal time:
var d = new Date();
var n = d.toUTCString();
The result of n will be:
Mon, 28 Dec 2015 12:57:32 GMT

Compare two unix time stamps to see if they are on the same date in MySql

I have read various questions here on Stackoverflow about the use of FROM_UNIXTIME but none directly deal with what I am trying to do. I have one timestamp in a variable coming from php (that has been reformatted - e.g. 25 March 2014) to a function which uses a database query to determine if there are other entries in the database that have the same date (not time). I've run across various methods for formatting and comparing timestamp entries using MySql and ended up with the following but I understand that it isn't very efficient. Does anyone know of a better way to accomplish this?
FROM_UNIXTIME(sd.timestart, "%e %M %Y") = ?'
where the variable in my array for comparison is the date format listed above. This accomplishes what I want but, again, I don't think it is the most efficient way to get this done. Any advice and/or ideas will be much appreciated.
*EDIT*
My timestamp is stored as an integer so I'm trying to use:
$thissessiondate = strtotime($date->timestart, strtotime('today'));
and
$tomorrowdate = strtotime($date->timestart, strtotime('tomorrow'));
to do trim to midnight but get an error (strtotime() expects parameter 2 to be long) and when I move 'today' to the first argument position, I get a conversion to 11 pm instead of 0:00...? I'm making some progress but my very incomplete knowledge of both PHP and MySQL are holding me back.
If you can avoid it, don't wrap columns used in predicates in expressions.
Have your predicates on bare columns to make index range scans possible. You want the datatype conversion to happen over on the literal side of the predicate, wherever possible.
The STR_TO_DATE function is the most convenient for this.
Assuming the timestart column is DATE, DATETIME or TIMESTAMP (which it really should be, if it represents a point in time.)
WHERE sd.timestart >= STR_TO_DATE( ? , "%e %M %Y")
AND sd.timestart < STR_TO_DATE( ? , "%e %M %Y") + INTERVAL 1 DAY
Effectively, what that's doing is taking the string passed in as the first argument to the STR_TO_DATE function, MySQL is going to convert that string to a DATETIME, based on the format specified as the second argument. And that effectively becomes a literal that MySQL can use to compare to the stored values in the column.
If there's an appropriate index available, MySQL will consider an index range scan operation to satisfy that predicate.
You'd need to pass in the same value twice, but that's not really a problem.
On the second line, we're just adding a day to the same value. So what MySQL is seeing is this:
WHERE sd.timestart >= STR_TO_DATE( '25 March 2014' , "%e %M %Y")
AND sd.timestart < STR_TO_DATE( '25 March 2014' , "%e %M %Y") + INTERVAL 1 DAY
In terms of performance, that's equivalent to:
WHERE sd.timestart >= '2014-03-15 00:00:00'
AND sd.timestart < '2014-03-16 00:00:00'
If you do it the other way around, and wrap timestart in a function, that's going to require MySQL to evaluate the function on every single row (or at least, on every row that isn't filtered out by another predicate first.)
IMPORANT NOTE
Be aware that MySQL interprets datetime values as being in the timezone of the MySQL connection, which defaults to the timezone setting of the MySQL server. MySQL is going to interpret datetime literals in the current setting of the timezone. For example, if MySQL timezone is set to +00:00, then datetime literals will be interpreted as UTC.
I assumed the format string matches the data being passed in, I don't use %e or %m. The %Y is a four digit year. (The list of format elements is in the MySQL documentation, under the DATE_FORMAT function.
Reference: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date
If your timestart column is INTEGER or other numeric datatype, representing a number of seconds or some other unit of time since the beginning of an era, you can use the same approach for performance benefits.
In the predicate, reference bare columns from the table, and do any conversions required on the literal side.
If you aren't using MySQL functions to do the conversion to "seconds since Jan 1, 1970 UTC" when rows are inserted (which is really what the TIMESTAMP datatype is doing internally), then I wouldn't recommend using MySQL functions to do the conversion in the query either.
If you're doing the conversion from date and time to an integer type "timestamp" in PHP, then I'd do the inverse conversion in PHP as well, and do the trimming to midnight and the adding of a day in PHP.
In that case, your MySQL query would be of the simple form:
WHERE sd.timestart >= ?
AND sd.timestart < ?
Where you would pass in the appropriate integer values, to compare to the INTEGER timestamp column.
Note that MySQL does provide a function for converting to "seconds since Jan 1 1970 UTC", so if timestart is seconds since Jan 1 1970 UTC, then something like this is valid:
WHERE sd.timestart >= UNIX_TIMESTAMP(STR_TO_DATE( '25 March 2014' , "%e %M %Y"))
AND sd.timestart < UNIX_TIMESTAMP(STR_TO_DATE( '25 March 2014' , "%e %M %Y") + INTERVAL 1 DAY)
BUT... again, be aware of timezone conversion issues; if the MySQL database has a different timezone setting than the web server. If you are going to store "integer", then I wouldn't muck that up with the conversion that MySQL does, which may not be exactly the same as the conversion functions the web server does.
If you store your date as an int timestamp, you can do this
round(sd.timestart/86400)=round(UNIX_TIMESTAMP(NOW())/86400)
This will get everything in your database that is from the same day.
For example:
SELECT id FROM uploads WHERE (approved=0 OR approved is NULL) AND round(uploads.date/86400)<=round(UNIX_TIMESTAMP(NOW())/86400) order by uploads.date DESC LIMIT 20
Will display all the uploads for today and the days before, without showing the future uploads. 86400 is the number of seconds in one day.

select a date lesser than a particular date

I have stored the dates as string in my database.I know it is not good,but project already has been half developed before i take over and where dates were stored as string,so i was continuing the same way.
Now i want to select dates from table where date is greater than a specific date.
I tried the following query
SELECT
*
FROM
dates
where
STR_TO_DATE(date, '%Y-%m-%d') > "2014-01-01"
but it is not returning only greater values.
Please help me to solve problem.
Demo
Your dates are not in YYYY-MM-DD format. Use the right format!
SELECT *
FROM dates
where STR_TO_DATE(date, '%m-%d-%Y') > date('2014-01-01')
If you are going to store dates as strings, then the best way is in the ISO format of YYYY-MM-DD.
You should read the documentation on str_to_date() (here).
Convert everything to date and it should be fine. Now you are comparing date and string.
What type has the date? I'd prefer a ' instead of " for strings in SQL. Let's assume that date is a VARCHAR or TEXT field (depending on which database you are using):
SELECT *
FROM dates
WHERE STR_TO_DATE(date, '%Y-%m-%d') > STR_TO_DATE('2014-01-01', '%Y-%m-%d')
If date is a real DATE
SELECT *
FROM dates
WHERE trim(date) > STR_TO_DATE('2014-01-01', '%Y-%m-%d')
Or you just convert it into a number format date_format(date,'%Y%m%d') > 20140101

Read data stored as text and use in IF statement

I have a column that stores dates as text, I need to select all the entries with date less than the date of today.
If I use this:
SELECT *
FROM mytab
WHERE expire < CURRENT_DATE( )
ORDER BY expire DESC
It doesn't select the correct entries but only the ones with da_expire empty.
How can I fix it?
In the first place, why are you storing it as string?
You need to convert it to date using MySQL's builtin function so you can be able to compare it with today's date.
WHERE STR_TO_DATE(expire, '%Y/%m/%d %H:%i') < CURDATE()
This will be a little slower since it will not use any index if you have one defined on the column.
MySQL Docs: STR_TO_DATE()
Use STR_TO_DATE(expire, '%m/%d/%Y') instead of expire in the query. I have assumed you are storing the date in month day year format. You will need to adjust the format as per the string format. However, for performance reasons convert the type of expire during load/insert process .