Need to combine timestamp field date with varchar field time - mysql

Im trying to figure out a way to fix a database schema issue.
In column 1 a y-m-d H:i:s date is stored (timestamp field)
col1 = 2009-11-12 00:00:00
In column 2 a time is stored (varchar)
col2 = 15:48
I'm thinking that storing it in one column would be more efficient than separately, so I'm trying to make column 3 a datetime field
col3 = 2009-11-12 15:48:00
Unless keeping it original is fine.

Yes, definitely use one field, you can get just the date or time from it later if you need. I believe you can run the following query to update col3 with the correct datetimes.
UPDATE tablename
SET col3 = CAST(LEFT(col1, 10) + " " + col2 + ":00", DATETIME)
If you don't have anything accessing these old fields (col1 and col2), you should get rid of them for clarity. If you do, it is going to be tricky decided whether or not to maintain two fields for the same data.

Addtime should do what you need
mysql> select addtime('2012-05-05 00:00:00', '11:12');
+-----------------------------------------+
| addtime('2012-05-05 00:00:00', '11:12') |
+-----------------------------------------+
| 2012-05-05 11:12:00 |
+-----------------------------------------+
1 row in set (0.00 sec)

Contrary to the other answers... I wouldn't immediately suggest combining these columns.
Consider how the columns are going to be queried - in my experience, efficient queries are more important than disk space efficiency - as such, if you're want to select rows based on date (ignoring time) and/or time (ignoring date) you would want these in separate columns. Whilst you can get the date from a datetime column, if you have lots of rows, doing that on each row before running a query would be really inefficient. (For example... consider this SO question)

Related

Difference between DATE and DATETIME in WHERE clause

Lets say, I have a table:
+------------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------+------+-----+-------------------+-----------------------------+
| id | int(10) | NO | PRI | | AUTOINCREMENT |
| id_action | int(10) | NO | IDX | | |
| a_date | date | NO | IDX | | |
| a_datetime | datetime | NO | IDX | | |
+------------+-----------+------+-----+-------------------+-----------------------------+
Each row has some id_action, and the a_date and a_datetime when it was executed on the website.
My question is, when I want to return COUNT() of each id_action grouped by a_date, is it same, when I use this two selects, or they are different in speed? Thanks for any explanation.
SELECT COUNT(id_action), id_action, a_date
FROM my_table
GROUP BY a_date
ORDER BY a_date DESC
and
SELECT COUNT(id_action), id_action, DATE_FORMAT(a_datetime, '%Y-%m-%d') AS `a_date`
FROM my_table
GROUP BY DATE_FORMAT(a_datetime, '%Y-%m-%d')
ORDER BY a_date DESC
In other words, my question is, that each action has its datetime, and if I really need column a_date, or it is the same using DATE_FORMAT function and column a_datetime and I dont need column a_date?
I ran both the queries on similar table on MySQL 5.5.
The table has 10634079 rows.
First one took 10.66 initially and always takes approx 10 secs on further attempts.
Seconds Query takes 1.25 mins to execute first time, on second, 3rd.... attempts its taking 22.091 secs
So in my view, if your are looking for performance, then you must have column a_date, as its taking half of the time when executed without Date_Format.
If performance is not the primay concern (like data redundancy can be) then a_datetime column will serve all other date/datetime related purposes.
DATE : The DATE type is used for values with a date part but no time part.
DATETIME: The DATETIME type is used for values that contain both date and time parts.
so if you have DATETIME you can always derive DATE from it but from DATE you can not get DATETIME.
And as per your sql there will not be a major difference.
It will be better not to have a_date because you already have a_datetime.
but in general if you can use TIMESTAMP you should, because it is more space-efficient than DATETIME.
Using a_date to group by day will be more efficient than a_datetime because of your conversion. In T-SQL I use a combination of DATEADD() and DATEDIFF() to get the date only from DATETIME since math is more efficient than data conversion. For example (again, using T-SQL though I'm sure there's something similar for MySQL):
SELECT COUNT(id_action), id_action,
DATEADD(DD,DATEDIFF(DD,0,a_datetime),0) AS [a_date]
FROM my_table
GROUP BY DATEADD(DD,DATEDIFF(DD,0,a_datetime),0) AS [a_date]
ORDER BY a_date DESC
This will find the number of days between day 0 and a_datetime then add that number of days to day 0 again. (Day 0 is just an arbitrary date chosen for it's simplicity.)
Perhaps the MySQL version of that would be:
DATE_ADD('2014-01-01', INTERVAL DATEDIFF('2014-01-01',a_datetime) DAY)
Sorry I don't have MySQL installed or I would try that myself. I'd expect it to be more efficient than casting/formatting but less efficient than using a_date.
If you are doing a function in your group by clause: "GROUP BY DATE_FORMAT(a_datetime, '%Y-%m-%d')", you will not be leveraging your index: "a_datetime".
As for speed, I believe there will be no noticeable difference between indexing on datetime vs date (but it's always easy to test with 'explain')
Lastly, you can always read a datetime as a date (using cast functions if need be). Your schema is not normalized if you have both a a_date and a_datetime. You should consider removing one of them. If date provides enough granularity for your application, then get rid of datetime. Otherwise, get rid of a_date and cast as required
As already mentioned, the performance of any function(o_datetime) will be worse than just a_date. The choice depends on on your needs, if there is no need to DATETIME, take a DATE and that is.
If you still need to find a function to convert, then I advise you to take a date().
See also How to cast DATETIME as a DATE in mysql?
Put the two statements in editor SQL and execute (CTRL-L) statistics.
https://technet.microsoft.com/en-us/library/ms178071%28v=sql.105%29.aspx
https://msdn.microsoft.com/pt-br/library/ms190287.aspx?f=255&MSPPError=-2147217396

Incrementally update date field column based on order of a second column

MSQL DB for WordPress site.
I would like to update a date column for each row in a table, setting the date/time to an incrementing value (e.g. increment value by 1 day). The order that I do the updates should be based on the textual sort of another column in the row. The actual date value used isn't relevant (it could start at 2001-01-01 00:00:00 and increment in seconds, minutes, hours or days).
Example of two columns in the table:
field_date , title_text
2014-08-20 09:00:27, AAA-Entry
2014-08-24 10:00:00, ZZZ-Entry
2014-08-27 10:15:00, MMM-Entry
So, the row with the first 'title_text' (alphabetical sorting) should get the newest date. The next row based on title_text should get a slightly older date and so on until the last row (based on title_text) has the oldest date. So the data shown above would end up looking something like:
field_date , title_text
2000-01-03 00:00:00, AAA-Entry
2000-01-01 00:00:00, ZZZ-Entry
2000-01-02 00:00:00, MMM-Entry
After the update then the command:
select * from tbl_name order by field_date
would show output that would also be in alphabetical order of the title_text field. This would be equivalent to running:
select * from tbl_name order by title_text
I'm looking at:
[Incrementing datetime field with an update statement for SQL2005 and trying to get this to work on mySQL as I think this would work (I just change the 'order by' statement to 'order by title_text'). But I'm having problems with converting this to mySQL.
I'd appreciate any suggestions on different approaches or with getting the above solution to work in mySQL.
Thanks
Ian
Note: The reason behind this is that Wordpress populates list boxes/search results, based on the posting date, but I want it to be ordered based on the title text. There may be a 'Wordpress' answer (or plugin) to do this (and if you know, please feel free to tell me ;-) ), but from a learning viewpoint, I'd also like to understand how this was possible using mySQL.
In MySQL, you can do updates with sorts. The easiest way is to define a variable first and then do the update:
set #rn = -1;
update t
set field_date = date('2000-01-01') + interval (#rn := #rn + 1) day
order by title_text desc;

Getting date and time of datetime (bug in MySQL?)

Running the following statement, MySQL seems to mix things up:
select now(), if(false, date(now()), time(now()));
| 2013-07-24 10:06:21 | 2010-06-21 00:00:00 |
If replacing the second argument of the if with a literal string, the statement behaves correctly:
select now(), if(false, 'Banana', time(now()));
| 2013-07-24 10:06:21 | 10:06:21 |
Is this a bug or some really strange quirk?
The return type of IF has to be a datatype that includes the types of both arguments. So if one of the arguments is a DATE and the other is a TIME, the type of IF will be DATETIME.
This doesn't seem necessary in the trivial example query, but consider something like:
SELECT IF(col1, date(col2), time(col2)) AS dt
FROM Table
All the rows of the result have to have the same datatype in the dt column, even though the specific data will depend on what's in that row.
If you want just the date or time, convert it to a string.

Correct MySQL Structure for a Time Range for Query Optimization?

I have a scenario where I want to be able to SELECT rows from a MySQL table, but exclude rows where the current time-of-day is inside a time-range.
Example:
The "quiet" period for one row is 10pm - 8:30am.
My SQL SELECT statement should not return that row if the current server time is after 10pm or before 8:30am.
Example 2: The "quiet period" is NULL and ignored.
Example 3: A new row is created with a quiet period from 9:53am to 9:55am. If the current server time is in that 2-minute window, the row is not returned by the SELECT.
My question:
What data format would you use in the database, and how would you write the query?
I have thought about a few different approaches (defining start_time as one column and duration as another, defining both in seconds... or using Date stamps... or whatever). None of them seem ideal and require a lot of calculation.
Thanks!
I would store the start and end dates as MySQL native TIME fields.
You would need to consider ranges that span midnight as two separate ranges but you would be able to query the table like this, To find all current quiet periods
SELECT DISTINCT name FROM `quiet_periods`
WHERE start_time<=CURTIME() AND CURTIME()<=end_time
Or to find all non-active quiet periods
SELECT name FROM quiet_periods WHERE name NOT IN (
SELECT name FROM `quiet_periods`
WHERE start_time<=CURTIME() AND CURTIME()<=end_time
)
So with sample data
id -- name -- start_time -- end_time
1 -- late_night -- 00:00:00 -- 08:30:00
2 -- late_night -- 22:00:00 -- 23:59:59
3 -- null_period -- NULL -- NULL
4 -- nearly_10am -- 09:53:00 -- 09:55:00
At 11pm this would return
null_period
nearly_10am
from the second query.
Depending on performance and how many rows you had you might want to refactor the second query into a JOIN and probably add the relevant INDEXes too.

Storing a date where only the year may be known

What's the best way to store a date value for which in many cases only the year may be known?
MySQL allows zeros in date parts unless the NO_ZEROES_IN_DATE sql mode is enabled, which isn't by default. Is there any reason not to use a date field where if the month and day may be zero, or to split it up to 3 different fields for year, month and day (year(4), tinyint, tinyint)?
A better way is to split the date into 3 fields. Year, Month, Day. This gives you full flexibility for storing, sorting, and searching.
Also, it's pretty trivial to put the fields back together into a real date field when necessary.
Finally, it's portable across DBMS's. I don't think anyone else supports a 0 as a valid part of a date value.
Unless portability across DBMS is important, I would definitely be inclined to use a single date field. If you require even moderately complex date related queries, having your day, month and year values in separate fields will become a chore.
MySQL has a wealth of date related functions - http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html. Use YEAR(yourdatefield) if you want to return just the year value, or the same if you want to include it in your query's WHERE clause.
You can use a single date field in Mysql to do this. In the example below field has the date data type.
mysql> select * from test;
+------------+------+
| field | id |
+------------+------+
| 2007-00-00 | 1 |
+------------+------+
1 row in set (0.00 sec)
mysql> select * from test where YEAR(field) = 2007;
+------------+------+
| field | id |
+------------+------+
| 2007-00-00 | 1 |
+------------+------+
I would use one field it will make the queries easier.
Yes using the Date and Time functions would be better.
Thanks BrynJ
You could try a LIKE operative. Such as:
SELECT * FROM table WHERE date_feield LIKE 2009;
It depends on how you use the resulting data. A simple answer would be to simply store those dates where only the year is known as January 1. This approach is really simple and allows you to aggregate by year using all the standard built in date functions.
The problem arises if the month or date is significant. For example if you are trying to determine the age of a record in days, weeks, months or if you want to show distribution across this smaller level of granularity. This problem exists any way, though. If you have some full dates and some with only a year, how do you want to represent them in such instances.