I've been searching the internet for almost 6 hours now for the fastest solution to my problem.
I've got a SQL Server database where some of the tables have a DATETIME format for columns, but the values in these columns are in the following format:
DD-MM-YYYY HH:MM
eg.
18-12-2012 00:00
From my research MySQL only accepts the following format for its DATETIME values:
YYYY-MM-DD HH:MM:SS
Now, I'm actually trying to make the conversion in the Scripts themselves, not the database.
basically I have over 250,000 records in multiple tables in SQL Server Script Format.
I've already changed all the syntax to MySQL except this part.
Any help or advice would be appreciated. URGENT.
thank you
This is the Table
CREATE TABLE Price(
AirlineCode char(2) NOT NULL
, FlightNumber varchar(6) NOT NULL
, ClassCode char(3) NOT NULL
, TicketCode char(1) NOT NULL
, StartDate DateTime NOT NULL
, EndDate DateTime NOT NULL
, Price decimal NOT NULL
, PriceLeg1 decimal NULL
, PriceLeg2 decimal NULL
, PRIMARY KEY (
AirlineCode,
FlightNumber,
ClassCode,
TicketCode,
StartDate
)
, FOREIGN KEY (AirlineCode) REFERENCES Airlines (AirlineCode)
, FOREIGN KEY (ClassCode) REFERENCES TicketClass (ClassCode)
, FOREIGN KEY (TicketCode) REFERENCES TicketType (TicketCode));
and this is a sample insertion:
INSERT INTO Price VALUES ( 'QF', 'QF67', 'ECO', 'E', '18-12-2012 00:00', '04-01-2013 00:00', 3427.82, 1636.14, 2045.20 );
You can use MySQL STR_TO_DATE() function to convert dates from a known format to a datetime value. Assuming that you have dates in dd-mm-yyyy hh:mm (all numbers 0 padded and hh:mm is a 24-hour time) you can use:
SELECT STR_TO_DATE('18-12-2012 00:00', '%d-%m-%Y %k:%i')
-- 2012-12-18 00:00:00
You can use this function in your insert queries like so:
INSERT INTO Price VALUES (
'QF',
'QF67',
'ECO',
'E',
STR_TO_DATE('18-12-2012 00:00', '%d-%m-%Y %k:%i'),
STR_TO_DATE('04-01-2013 00:00', '%d-%m-%Y %k:%i'),
3427.82,
1636.14,
2045.20
);
Edit
If editing your insert queries is not possible, you can let MySQL do all the conversion. Temporarily change the datatype of datetime columns to VARCHAR and import the data. Then add a temporary field e.g. StartDate_Temp DATETIME and run an update query:
UPDATE Price SET StartDate_Temp = STR_TO_DATE(StartDate, '%d-%m-%Y %k:%i')
Once you've verified that your data is OK, delete the temporary columns.
Edited answer:
Also, you may use RegEx in SQL Server Management Studio:
Find what: {[0-9][0-9]}\-{[0-9][0-9]}\-{[0-9][0-9][0-9][0-9]} {[0-9][0-9]}\:{[0-9][0-9]}
Replace with:\3-\2-\1
First of all I would like to say thank you to all for your efforts. This was the first question I've ever asked at StackOverflow.com and am really impressed by the level of support.
After a little bit more research, I remembered the good old toolkit of RegEx that I learnt last year. So I decided to put it in some good use.
in Notepad++ thanks to its Regex search capabilities, I managed to trace down every date value in my 250000 records and replace them with the required ones.
([0-9][0-9])-([0-9][0-9])-([0-9][0-9][0-9][0-9]) ([0-9][0-9]:[0-9][0-9])
this was the search I put through for the date format that I had, and then i swapped the year and the day values and added the seconds in there as well by having the following in the Replace with box:
\3-\2-\1 \4:00
Problem solved.
Related
I am using MySQL Version 5.7.28. I am having json data like below.
CREATE TABLE `week2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` smallint(1),
`json` text ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO week2(id,type,json)
VALUES
(121,1,'[{"weekdays":"Sunday"},{"weekdays":"Monday"},{"weekdays":"Tuesday"},{"weekdays":"Wednesday"},{"weekdays":"Thursday"},{"weekdays":"Friday"},{"weekdays":"Saturday"}]'),
(122,1,'[{"weekdays":"Sunday"},{"weekdays":"Monday"}]'),
(123,2,'[{"start_time":"08:00 AM","end_time":"10:00 PM"}]');
As you see, the json column has nested JSON data. so here i am looking to compare today's day ( which is Saturday and we are currently in between start time and end time)
Expected Result:
(121,1,'[{"weekdays":"Sunday"},{"weekdays":"Monday"},{"weekdays":"Tuesday"},{"weekdays":"Wednesday"},{"weekdays":"Thursday"},{"weekdays":"Friday"},{"weekdays":"Saturday"}]'),
(123,2,'[{"start_time":"08:00 AM","end_time":"10:00 PM"}]');
You need to detect day name (1) and time period (2), and combine those two conditions by OR operator at the end.
For (1) : Detect the current day's name by using DAYNAME() function and search whether exists in the JSON data containing weekday keys through use of JSON_CONTAINS function.
For (2) : TIME() function and CASTing strings to TIME data type might be used with a trick to add 12 hours iterations for the cases of PM type times.
So, consider using :
SELECT *
FROM `week2`
WHERE JSON_CONTAINS(`json`->>'$[*].weekdays', CONCAT('"',DAYNAME( NOW() ),'"')) = 1
OR
(
TIME(ADDTIME(NOW(),"8:00:00")) >=
CASE WHEN INSTR(REPLACE(`json`->>'$[0].start_time',"12:00 AM","00:00 AM"),"PM")>0
THEN
CAST(CONCAT(MOD((TIME_FORMAT(REPLACE(`json`->>'$[0].start_time',"12:00 AM","00:00 AM"), "%T")+12),24),":00 AM")
AS TIME)
ELSE
CAST((REPLACE(`json`->>'$[0].start_time',"12:00 AM","00:00 AM")) AS TIME)
END
AND
TIME(ADDTIME(NOW(),"8:00:00")) <=
CASE WHEN INSTR(REPLACE(`json`->>'$[0].end_time',"12:00 AM","00:00 AM"),"PM")>0
THEN
CAST(CONCAT(MOD((TIME_FORMAT(REPLACE(`json`->>'$[0].end_time',"12:00 AM","00:00 AM"), "%T")+12),24),":00 AM")
AS TIME)
ELSE
CAST(REPLACE(`json`->>'$[0].end_time',"12:00 AM","00:00 AM") AS TIME)
END)
Demo
Perhaps, something like this:
SELECT *,CURRENT_TIME
FROM
(SELECT *,JSON_UNQUOTE(JSON_EXTRACT(`json`,'$[0].start_time')) AS st,
JSON_UNQUOTE(JSON_EXTRACT(`json`,'$[0].end_time')) AS et FROM week2) V
WHERE (JSON_SEARCH(`json`, 'one', DAYNAME(CURDATE())) IS NOT NULL
OR
CURRENT_TIME hour >=
CASE WHEN st LIKE '%AM%' THEN REPLACE(st,' AM',':00')
WHEN st LIKE '%PM%' THEN SEC_TO_TIME(TIME_TO_SEC(REPLACE(st,' PM',':00'))+43200)
END
AND
CURRENT_TIME hour <=
CASE WHEN et LIKE '%AM%' THEN REPLACE(et,' AM',':00')
WHEN et LIKE '%PM%' THEN SEC_TO_TIME(TIME_TO_SEC(REPLACE(et,' PM',':00'))+43200)
END);
First query is using JSON_EXTRACT to extract the time and JSON_UNQUOTE to remove the (") then make it as a sub-query.
On the outer-query, find the weekdays value using JSON_SEARCH compare with today's DAYNAME(CURDATE()); if JSON_SEARCH doesn't find it, it will return NULL, hence the IS NOT NULL condition is used.
Append OR to compare CURRENT_TIME with the time value extracted from the json field. But first, using CASE expression to find out if it's AM or PM; if it's AM, just REPLACE the AM with seconds hand (:00). If it's PM, do the REPLACE like AM then convert the time value to seconds using TIME_TO_SEC then add 43200 seconds (12 hours) and convert again to standard hour:minute:second format using SEC_TO_TIME.
P/S: It was my attempt to answer but I didn't post it because I get wrong result with the time.. Only when I put CURRENT_TIME in the fiddle that I realized that the fiddle time zone is different that mine. Also, I was testing on my local DB; which is MariaDB and the results of converting string to time using STR_TO_TIME is different. Honestly, in my opinion, if this is MariaDB, I think there's a chance that the query is much shorter.
I have a week column with week numbers as w0, w1, w2.... I am trying to get last last six weeks data. Here's the sql query I am using.
SELECT * FROM week
WHERE uid = '9df984da-4318-1035-9589-493e89385fad'
AND report_week BETWEEN `'w52' AND 'w5'`;
'w52' is essentially week 52 in December 2015 and 'w5' is Jan 2016. The 'between' seems to not work. Whats the best way to get data from the above two weeks?
Here's the CREATE TABLE statement:
CREATE TABLE `week` (`uid` VARCHAR(255) DEFAULT '' NOT NULL,
`report_week` VARCHAR(7) NOT NULL,
`report_files_active` BIGINT DEFAULT NULL);
Essentially this table is getting populated from other table which has date column. It uses dates from other table and summarizes weekly data into this.
Any help is appreciated.
Refer to this SO Discussion which details the reasons for a problem similar to yours.
BETWEEN 'a' and 'b' actually matches to columnValue >='a' and columnValue <= 'b'
In your case w52 is greater than w5 due to lexicographic ordering of Strings - this means that the BETWEEN clause will never return a true (think about it as equivalent to saying BETWEEN 10 and 1 instead of BETWEEN 1 and 10.
Edit to my response:
Refrain from storing the week value as a string. Instead here are a couple of approaches in order of their preference:
Have a timestamp column. You can easily then use MySQL query
facilities to extract the week information out of this. For a
reference see this post.
Maintain two columns - YEAR, WEEKNO where YEAR will store values
like 2015, 2016 etc and WEEKNO will store the week number.
This way you can query data for any week in any year.
please show me table structure and DB name because it different for other, if it is any timestamp then we can use BETWEEN 'systemdate' AND 'systemdate-6'
I have created MySQL table :
CREATE TABLE EMP(
EMPID INTEGER NOT NULL (5),
SURNAME VARCHAR(25),
SAL INTEGER(5),
JON VARCHAR(25),
START_DATE DATE,
END_DATE DATE,
DEPNO INTEGER(5)
);
with following records:
INSERT INTO EMP
(EMPID,SURNAME,SALARY,JOB,START_DATE,END_DATE,DEPNO)
VALUES
('1','Vorosila','500000','COO','20150101',null,'1');
however I need to change date format from 2015 01 01 to 01 01 2015
Can anybody show me or tell me how to do that ?
THANK YOU IN ADVANCE
DATE values do not have a "format", they are objects that represent instants in time (or entire days, but still independent of formatting).
Formats are applied on input and output, so you just need to apply the correct format, which you can find in the MySQL manual, to the SELECT statement.
You cannot change the default date format in mysql.
I once hoped for the default date to be editable so I wouldn't have to jump through these hoops to get the date I actually wanted, mysql even has a date format system variable, but it is unused. Date Format Mysql - link
What you should really do is store it as the default format Year-Month-Date and then convert it on select.
The first thing I'd suggest is having your date columns as date types, which would give your dates the following format '2015-01-01'.
If you do this then you can use DATE_FORMAT - link - the second value in the DATE_FORMAT function allows you to customise the returned date, and there are many different thing you can do with this if you look at the link:
SELECT
DATE_FORMAT(`START_DATE`,'%d-%m-%Y')
AS `START_DATE`
FROM ...
The other option you have is to store your dates in the format that you already want as a char or varchar column.
HOWEVER, as should be obvious, this column will not be treated as storing dates, and so will not give you the correct comparisons in a where clause when using > < BETWEEN or the correct ordering in an order by clause. It is after all just a string of numbers in this case.
However you can then use STR_TO_DATE - link if you did need to use a where or order by on this column to change it back to a date within the query - in this case the second value is the custom format of your 'dates' in the column. Keep in mind with a where you will need to compare it with the correct mysql format as shown below:
SELECT
`START_DATE`
FROM table
WHERE STR_TO_DATE(`START_DATE`,'%d-%m-%Y') BETWEEN '2015-01-01' and '2016-01-01'
In MySQL you can change the format of a date using DATE_FORMAT method which is similar to to_char in Oracle.
DATE_FORMAT(SYSDATE(), '%DD-%MM-%YYYY');
For more information about specifiers check this thread http://www.sqlines.com/oracle-to-mysql/to_char_datetime
You can do what you probably want by creating a view and referring to that instead of the (underlying) table.
CREATE VIEW emp_view AS
SELECT empid,
surname,
sal,
jon,
date_format(start_date, '%d-%m-%Y') as start_date,
date_format(end_date, '%d-%m-%Y') as end_date,
depno
FROM emp;
Note that this changes the type of the date columns to varchar, so comparisons will no longer work as expected:
SELECT * FROM emp_view WHERE start_date > '01-12-1924'; // fails!
I have a VARCHAR field completion_date that contains a timestamp date (ex 1319193919). Is it possible to run a query on such a field that compares it with NOW() ? I'm trying:
SELECT * FROM (`surveys`) WHERE `active` = '1' AND `archived` = '0' AND `completion_date` > 'NOW()'
But the results are not really what I'm expecting, is this cause of the VARCHAR? If so, what kind of date field am I better off using? The data must remain a Linux timestamp.
Convert NOW() to a timestamp using UNIX_TIMESTAMP()
SELECT *
FROM (`surveys`)
WHERE `active` = '1' AND `archived` = '0' AND `completion_date` > UNIX_TIMESTAMP(NOW())
Also, remove the quotes you had around 'NOW()'
mysql> SELECT UNIX_TIMESTAMP(NOW());
+-----------------------+
| UNIX_TIMESTAMP(NOW()) |
+-----------------------+
| 1319288622 |
+-----------------------+
N.B. In case you need it, the inverse of this function is FROM_UNIXTIME() to convert a timestamp into the default MySQL DATETIME format.
As mentioned in comments below, if you have the ability to make the change, it is recommended to use a real DATETIME type instead of VARCHAR() for this data.
A Linux timestamp can easily be stored in a BIGINT (or an UNSIGNED INT), which would make the type of comparisons you're trying to do possible. A VARCHAR is going to do a lexical, not numeric, comparison and which is NOT what you want. Using a BIGINT in conjunction with converting NOW() with UNIX_TIMESTAMP() should get you what you want.
It might even be better to store it using a DATETIME data type and do the conversion when you select the data. Storing it as a DATETIME future proofs your application in the event that you move to or add a different platform where a Linux timestamp isn't appropriate. Then you only need to modify your code, not convert your data to have it continue to work. I'm working on a project now where dates were stored as character data and it's been no end of problems getting the old data into shape to use with the new application, though you might experience fewer problems than us because you're storing a time stamp, not a formatted date, with its attendant typos.
SQL beginner here !
What is the most convenient way to create datetime objects within an SQL function, especially generating a datetime object for a given day, month, and year?
Thanks !
Everything you want to know about MySQL datetime functions is right here. Well, probably most everything.
In MySQL
CAST('YYYY-MM-DDThh:mm:ss:uuuuuu' AS datetime)
where:
YYYY: Year
MM : Month
DD : Day
hh : Hour
mm : Minutes
ss : Seconds
uuuuuu : Microseconds
EDIT: I changed from mmm (miliseconds) to uuuuuu (microseconds) since MySQL suports 6 digits
Given a datetime column: INSERT INTO Table ('datetime_column') VALUES (CURDATE( ))
Given a timestamp: INSERT INTO Table ('timestamp_column') VALUES (CURTIME())
Using unix time: INSERT INTO Table ('timestamp_column') VALUES (UNIX_TIMESTAMP())