Storing day and month (without year) - mysql

I'm having trouble with figuring out the best way to store some data in my database. I've got to store DD/MM dates in a database, but I'm not sure of the best way to store this so that it can be easily sorted and searched.
Basically a user will be able to save important dates in the format DD/MM, which they will be reminded of closer to the day.
The DATE data type doesn't seem completely appropriate as it includes year, but I can't think of another way of storing this data. It would be possible to include a specific year to the end of all occasions, but this almost doesn't seem right.

I've got to store DD/MM dates in a database, but I'm not sure of the best way to store this so that it can be easily sorted and searched.
The best way to store date data, even if the year component is not required, is to use date. When you need to use it, you can remove the year, or replace it with the year being compared against (or current year).
Having it in date column facilitates sorting correctly, integrity, validation etc.
To cater for leap years, use a year like '0004' which allows '0004-02-29'. Using year 4 makes it slightly more complicated than year 0, but as an example, this turns the date '29-Feb' (year agnostic) into a date in this year for comparison with some other field
select
adddate(
subdate(cast('0004-02-29' as date),
interval 4 year),
interval year(curdate()) year)
result: 2011-02-28

Are these dates recurring? If not, how will you keep track of when one has "expired"? If the answer is "the app will manually remove the dates once they have expired", then why not simply store the DD/MM date as the next available instance of that date? For example:
01/02 becomes 2012-02-01, and 04\07 becomes 2011-07-04
The built-in date/time functions are so useful that I strongly recommend you not use varchars or tinyints.

If you really really want to drop the year, then just make TWO columns, one for day and another for month. Then store them separately.
CREATE TABLE `table-name` (
`Day` tinyint NOT NULL,
`Month` tinyint NOT NULL
);
But, it's much better to just use the Date type and then ignore the year in your code.

Related

How can I save only the day/month part of a date?

I want to save in a database table the month and day part of a date. That will be fixed regardless of the actual year so I don't need to save the year as well.
I could define a type like: char(5) and save it as: 01-01 but this would not "protect" from garbage strings.
Is there a way to define it better? E.g. does an enum for month and day make sense? (though still something like 02-30 could be defined which is of course meaningless)
select to_char(to_date('2011-01-17', 'yyyy-mm-dd'),'dd-mm') from dual;
17-01
It`s written in Oracle, you can use logic from the Query for SQL.

Using MySQL to return row between to strings with date, but without year

I am currently working on a project in which I want to store commemorative days (like January 8th's World Leprosy Day) in a database. At this moment they're stored in a table which contains:
- an ID
- the date as varchar (stored European style, e.d. "8-01" for January 8th)
- length of the commemorative day (as some span multiple days)
- and the name
The reason I am storing the date as varchar is because the year is irrelevant, and I'm a bit reluctant to just store a year (e.g. 2013) in the database and truncate it.
But here's the problem: I can't seem to find a way to construct a query that will get the rows between dates. I think it's because the way the dates are stored in the database.
I already tried (given day = "8-01")
SELECT * FROM comdays WHERE date(day) BETWEEN date("1-01") AND date("20-01")
But to no avail.
Is there a way to get this thing going with strings? Or do I have to change the date column into a MySQL DATE format?
Thanks in advance!
If you really want to keep non standard date field in MYSQL you will need to use the following format 0108-> mmdd this format allows calculations.
It might also be worth reading the following answers to similar question Save day and month in database

MySQL datatype to store month and year only [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I'm writing a PHP application that will store STUDENT data in a MySQL relational database. I'm trying to find the best way / datatype to store a month and year together without the day.
I don't know whether I should just store it as a DATE and use PHP someway to just store the day as the 1-st or use a different datatype that I'm not currently familiar with. Ideally, I do not want to store a day, because the day will not always be the same and would require changing PHP source code if the day changed in the future.
Just for more background info, I'm storing a STUDENT's INTENT_TO_GRAD. The client seems to only want this information as a reference or a visual for a report as opposed to using it for data manipulation. In other words, the only functional requirement for this data is to be displayed in a report.
Why bother? Just store it as a complete date (perhaps always using the first as the day) and use the database functions MONTH() and YEAR() if you only need part of it. This makes using that field much easier as you can still do range queries, etc.
It says in the MySQL manual that you can store partial dates
http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_date-format
Ranges for the month and day specifiers begin with zero due to the
fact that MySQL permits the storing of incomplete dates such as
'2014-00-00'.
This means that to store the year and month only, you can use a DATE column and put 00 instead of the day. e.g 2013-12-00.
Related: Store incomplete date in MySQL date field
Consider how you are going to use the data. If there are any reports you have to create, which way would allow you to retrieve and work with the data more easily?
And you don't have to use a date type field. You could just have a Year field and a Month field that are both integers. Then when you actually need to do any kind of expression with it requiring a date it's easy enough to put them together and cast to a date.
And storing as a date with the day number as 1 and just ignoring it is perfectly okay and fairly normal too. In the end this isn't a decision that's going to matter a whole lot (relatively speaking) so I would just choose the one you like best and get it done.
Another solution is to build generated columns from your DATETIME/DATE source.
ALTER TABLE stats
ADD COLUMN year SMALLINT GENERATED ALWAYS AS (YEAR(stat_date)) NOT NULL,
ADD COLUMN month smallint GENERATED ALWAYS AS (MONTH(stat_date)) NOT NULL;
Background
I had a similar problem. After reading this thread, I decided to store incomplete dates (with zeros). It worked on older versions of MySQL, but newer versions produced "Incorrect date" error. As mentioned before, you can turn the error into warning using the NO_ZERO_IN_DATE setting. But the setting itself is deprecated. Hence, in the future, it would only be possible to support zeros in dates by disabling the strict mode, thus, silencing other types of errors.
Because NO_ZERO_IN_DATE is deprecated, it will be removed in a future MySQL release as a separate mode name and its effect included in the effects of strict SQL mode.
My requirement was to build a monthly view of a table. I had to add an index on month. So, computing moth on-the-fly with YEAR() and MONTH() was not an option.
Generated columns served their purpose. The year and month columns weren't part of the primary index, and I could even save space thanks to the VIRTUAL (not STORED) generated columns.
Links
https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date
https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html
I would store the two as two separate columns as integers. It would make validation cake and allow quick and easy sorting and grouping possibilities.
SELECT * FROM Users
WHERE
MONTH(DateTime) = '07'
AND
YEAR(DateTime) = '2015'
AND
DAY(DateTime) = '26'
you can filter like above but still if you want to store year/month and day as separate, its useless until you apply indexing and its very big data.
As of 5.7 one could make use of generated columns, which lets you enforce year-month uniqueness while also using date functions on another field without breaking data integrity by duplicating:
CREATE TABLE `year_month` (
`Year` int(11) NOT NULL,
`Month` enum(
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
) NOT NULL,
`GENERATED_YearMonth` date
GENERATED ALWAYS AS
((makedate(`Year`,1) + interval (`Month` - 1) month))
STORED,
PRIMARY KEY (`Year`,`Month`),
KEY `year_month_GENERATED_YearMonth_index` (`GENERATED_YearMonth`)
)
;
You can use VARCHAR datatype to store month and year only.
For those who use datepicker :-
1)Set VARCHAR datatype in mysql to store month and year.
2)If you are using jquery validation and have jquery plugin date picker then you have to do below code.
For ex:-
<script>
$(document).ready(function (){
$('#monthyear').datepicker({
autoclose:true,
format:'mm-yy'
});
//Your form validation code here//
});
</script>

How to find in MySQL the nearest (time wise) entry to a given date when only given year or only year and month?

This is very similar to a question that has already been answered (that I can't re-find right now) but the answers only let you get the nearest entry when you have a full date (year, month and day).
I'd go with DATEDIFF and construct a date string assuming '01' as the day / month. Not nice, but should work though.
A simple ABS(DATEDIFF()) might be exactly what's needed. But, for example, given the reference date of '2009', is 2009/01/10 or 2008/12/31 the correct date to return? Depending on your requirement you might use the middle of the period, or end, rather than the start.
Another consideration is what to do if more than one date is equally distant from the reference.
Given '2009' as the reference date, which is closest: 2009/06/30 or 2009/07/01? One interpretation might be that both are the same 'distance' from 2009 - zero years. Do you need to have some rule for picking just one date (could be a simple as just taking the first date) or do you want all 'equally distant' dates reported.

Sorting by month in MS Access

I am using an MS Access db to track some tasks during the year. Each task has a due Month. I do not want to use exact dates as the convention in my team is to refer to the month. I don't want to store the dates in a date format as team members will be entering the due month by hand.
Is it possible to sort my fields in date order if the date is stored as a text string month? (eg. January, February rather than 31/01/2009, 28/02/2009).
If so, what would such a query look like?
Thanks in advance.
If you are storing only the month name, your will first need to convert to a date to get a month number, use a lookup table (MonthNo, MonthName) or use the Switch function. Here is an example of converting to a date:
SELECT Month(CDate(Year(Date()) & "/" & [MonthNameField] & "/1")) AS MonthNo
FROM Table
However, there is probably a good argument for storing a date based on the month name entered, this would prevent any confusion about years.
This should work
SELECT *
FROM TableName
OrderBy Month(date_field)
I would store the month as an integer 1-12 then you can easily sort them.
I would make a date field.
I would store 1/1/2009 for January 2009, 2/1/2009 for February 2009, and so forth. For display purposes, I'd format it so that it displayed only the month (or Month + Year -- can't imagine how you wouldn't want the year).
This makes it possible to take advantage of date operations on the field without messy conversions of text to date formats.
Thank you all for your responses. Sorry for the delay in responding - I'm working on this issue again now.
For clarity, the DB is to be used to track a schedule of events within a 12 month period. The year does not need to be stored as everything in the DB is referring to the same year. A new copy of the DB will be made at the beginning of 2010.
I'm really keen to actually store the month as a word rather than any kind of value or date field as when bulk adding tasks I will likely edit the table directly rather than use a form.
I realise this is dead but google brought me here while i was looking so thought I would add to it:
I had this problem myself (Access 2010) and found a decent answer here: http://www.vbforums.com/showthread.php?503841-How-to-Convert-MonthName-to-Value(Microsoft-access-2003)
So what I did was have a Query which pulled out the DISTINCT months from my table. Then in the design view i added another column with MonthNo: Month(CDate("1 " & [Month]))and sorted the query on this column
hope this helps someone if not the OP.