tags:

views:

159

answers:

5

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: 

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

Mark Robinson
the like keyword in combination with the leading % results in a table scan. Indexes can't be used in that situation.
Chris Lively
Good point, he did say the year would be known, so there for be no need for the leading wildcard, it would be a limitation to keep in mind.
Mark Robinson
is a like query on a date column optimized to use prefix index matching at all? dates are stored internally as a 3-byte integer, not a string, so it has to cast it first.
ʞɔıu
Why not use the built-in date functions to retrieve the correct records? E.g. DAY, MONTH, YEAR etc. The first example would thus be SELECT * FROM test WHERE YEAR(field) = 2007 - semantically a lot clear too, and would use proper indices.
BrynJ
+1  A: 

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.

Chris Lively
+2  A: 

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.

BrynJ
A: 

You could try a LIKE operative. Such as: SELECT * FROM table WHERE date_feield LIKE 2009;

NJ
A: 

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.

Chris