ORDER BY date bugs - mysql

I know there's some of those questions on SO already, but I can't find the correct answer.
I'm trying to ORDER by a date that is formatet like this: 01-01-1999. My query looks like this:
SELECT id, header, date FROM table ORDER BY date DESC
I'm getting 4 rows which seems okay, (They are the same) but then I get some odd results further on.
The fields are VARCHAR(); - what field should it be to store 01-01-1999 formats in?
The odd results is that I'm getting 4x30-08-2012.. And then lots of old dates, but then suddenly there's 2 records with 13-09-2012.
My question is: How come it's not sorting them: 2x13-09-2012 and then 4x30-08-2012 and then further on.
UPDATE
The problem is solved. But still: What data-field would I use for my dates instead of VARCHAR?

juergen has given an answer which basically involves the date being parsed each time. Two other alternatives suggest themselves though:
Change your database schema so that the column is already a date type (e.g. DATE) rather than a string. Life is often a lot better when you make your database columns accurately represent the type of data you want to store in them.
If you really need to store the data in string columns, consider changing the format to yyyy-MM-dd. That's a naturally sortable format, in that the "alphabetic" ordering is compatible with the "semantic" ordering of dates.
The first option is definitely preferrable IMO. This goes way beyond ordering, to:
Validation (well, hopefully; I gather MySQL is rather more forgiving of invalid data than I personally like, but...)
Conversion: I'm not sure what the PHP support is like, but in general you should be able to send and receive date/time values to/from the database without converting them into strings, which removes error-prone conversions
Clarity of purpose: give us much help as possible to anyone examining the database. Whatever you know about the data, put it into the schema. If you store everything as varchar regardless of whether it's text, numeric or date/time data, you might as well say "Well, it's just some stuff"

try
SELECT id, header, date FROM table
ORDER BY str_to_date(date, '%d-%m-%Y') DESC
See STR_TO_DATE

The best way to store dates in strings is 'YYYY-MM-DD'. MySQL has native format for dates - DATETIME.

Related

What is the best practice to store a MM-DD data in MySQL?

I want to store some dates into MySQL but those dates are without years field.
What's the best way to do it?
It's best if I can utilize those two MySQL functions in my queries: DATE_SUB(), DATE_ADD(); because I want to query date spans that covers the current MM-DD.
ADD:
I have 100% control over the input and output code;
I have two MM-DD dates in a row to represent a date span
I'm not intending to save space by doing this, but I'm doing this just because in my requirements I need to store important MM-DD dates and return the date span that covers current MM-DD no matter what year it is now, it's like a "holiday reminder" or something like that
If you have 100% control over all the code that directly reads or writes this data, you could just use a normal DATE field, and always set the year to the same constant value.
Then, you can use DATE_ADD() etc. in your queries normally, you just have to omit the year whenever you return some of those dates.
What about storing the data using the date type and then just use the part of the date you need? In this way, if you'll change the behavior of you app, you can because you've thought your app thinking to the future (and to possible future change). Moreover you'll be able to use all the date built-in functions.
In addition, storing in some strange way just months and days, you will not even save space.

Is it a good idea to use string data type for dates in MySQL instead of using datetime data type?

While implementing web applications on top of MySQL database, I'm thinking if it is a good idea to just use string data type to store dates?
For example, I can just store dates as '201110191503999' into database. Also this is convenient to query by date. For example, select * from some_table where the_date like '20111019%'
Is there any performance issue if we use string for dates? and are there any advantages for using date/datetime data type?
Thanks in advance!
Always use the column type for what what is needed; if you are using a date, use DATETIME, if it is a timestamp, use TIMESTAMP and so on.
Depending on in what you are coding, all the formatting of the data can be done on the actual page in whatever language you are using.
Also, you can take advantage of MySQL functions such as NOW(), rather than using the language's version and then storing it into the database.
If your data is of date type then store the data in a DATE (or DATETIME if you have a time element to it).
If you store dates as strings then you are asking for trouble! For example, what is to stop somebody writing a value of 'I am not a date' into you string 'date' field? Or what happens if you have '20111019' and '2011-10-19' and want them to be treated as equal? Furthermore you will be missing out on a whole raft of MySQL DATE and TIME specific functions
Never store a date as a string if you can possibly avoid it.
I am thinking of doing the same thing. I have been wrestling with MySQL trying to get it to store a timezone independent value in the database - something based off GMT. It is really not working. Tried all kinds of flags useTimeZone=true and JDBCShift with Java - still not getting any liftoff. Also Kuala Lampur timezone does not work because of some exotic Java message. So, if you can control the format, sure, use a String type. Many have done it before.

Is it a bad idea using CHAR(6) to represent year+month field?

I am using MySQL and I have a field in a table that needs to store a year+month value. The field doesn't need the day, minute and second info. I am thinking to create the field as CHAR(6) because it seems to be fine using the >, = and < to compare the string.
SELECT '201108' < '201109'
>1
I want to use this format because I can insert the same string to Lucene index engine.
Is it a good idea or I should stick with DATE?
That will work fine, right up to the point where you have to implement your own code for working out the difference between two values, or figuring out what value you need for a time six months into the future.
Use the date type, that's what it's for (a). If is has too much resolution, enforce the constraint that the day will always be set to 1. Or force that with an insert/update trigger.
Then you can use all the fancy date manipulation code that your DBMS vendor has already written, code that's probably going to be much more efficient since it will be dealing with a native binary type rather than a character string.
And you'll save space in this particular case as well since a MySQL date type is actually shorter than a char(6). It's not often that a database decision gives you both space and time advantages (it's usually a trade-off), so you should seize them whenever you can.
(a) This applies to all of those types, such as date, time and datetime.
You'd want to use a date, but not store anything in the Day field. The database is more efficient at searching than your code will ever be because the database is optimized to handle lookups such as this one. You'd want to store a dummy value in the Day field to make this work.
Well, since MySQL only takes 3 bytes to store a date (Warning: The link is for MySQL version 5.0. Check the docs for your version to make sure), it would be better from a storage standpoint--as well as a performance standpoint when it comes to comparisons--to use date.
You can also use the Date Field for that and then while selecting the values you can use DATE_FORMAT function with that Date for selecting the year and month.
having field as Date type then
like the Date you entered is '2011-08-30'
Now you want the result as 201108 the write
select DATE_FORMAT('2011-08-30','%Y%m');
it will give result as 201108
for more detailed information for DATE_FORMAT please visit
http://davidwalsh.name/format-date-mysql-date_format

Mysql what field type to use for dates with a mix of full and part dates

I have a table that has three different date columns, so I set each column as type 'date'.
However whenever im importing dates it seems to change them, and I have found it is because mysql does not allow null days and months.
My dates range from
1909-00-00
1963-09-00
1907-11-30
so sometimes we dont know the month, sometimes the day, and sometimes only the year was recorded.
Surely the 'proper' way to do this is to use some kind of date field but I have tried a variety of different layouts when importing the data and non works :(
dd-mm-yyyy
mm-dd-yyyy
yyyy/dd/mm
Any suggestions?
There is no data structure that would act as a date but would allow 00 for any of the components. If you really insisted on emulating this, you could split the data into 3 columns - year, month, day and then write a complicated trigger to validate each update/insert query.
I wouldn't dare though. However, you asked, and I tried to answer. ;]
I would suggest using a varchar then converting it when ever you need it to be a date. Here is a site with some date functions that would be useful.

Best practice for storing the date in MySQL from PHP

I've been using the unix timestamp all my life.
I like it because it's easy to compare, it's fast because I store it as an integer. And since I'm using PHP, I can get any date/time format with date() function from the unixtimestamp.
Now, some people are saying that it's best to use the DATETIME format. But besides the more suited name, I don't see any advantages.
Is it indeed better to use DATETIME, if so, what are the advantages?
Thanks.
If you store dates as Unix timestamps in the database, you're giving yourself the heavy lifting. You have to convert them to the formats you want to use, you have to do the calculations between date ranges, you have to build the queries to get data in a range. This seems counter-intuitive- surely your "programmer time" is best spent solving real problems?
It seems much better practice to store dates and times in the proper format that MySQL has available, then use the database functions to create the queries for the data you want. The time you would waste doing all the convertions and mucking about is massive compared to the afternoon spent reading (and understanding) 11.6 MySQL Date and Time Functions
I've also been a huge fan of the unix timestamp all my life. But I think the correct answer is: "depends". I recently did a single table database where I wanted to only list URLs. There would be a date field, but the date field is purely for sorting. I.e order by last_crawled. Which means I will never use any built-in date functions on that field. It is merely an easy way to get the oldest entries first and I will never apply date functions to this field. Now, had I made this a date field, I would have lost out on two things:
A datetime field is twice the size of an integer
Sorting by an integer is faster (not 100% sure of this, pending outcome of this question)
However, for another system I had to store transactional information. This made using internal mysql date functions possible which turned out to be very useful when we had to start doing reports.
One advantage of using the MySQL date/time types is to be able to more simply use the date/time functions in MySQL.
The DATE type also has the advantage in that its only storing day, month and year so there is no space wasted or comparison complication that a seconds since epoch time would have for situations where you only cared about the day and not the time.
Personally I tend to use a database as just a dump for data so such functions are of little interest. In PHP I tend to just store the date in integer format for pretty much the reasons you state.
#Smita V, the inefficient query to which you refer is only so because you're applying your conversion function incorrectly to every table row, where you should apply it to the condition itself. So instead of
select col1,col2,colUnixdatetime from table where From_Unixtime(colUnixdatetime) between wtvdate1 and wtvdate2
, which converts every row on the table to compare it to the date you've got. You should use
select col1,col2,colUnixdatetime from table where colUnixdatetime between UNIX_TIMESTAMP(wtvdate1) and UNIX_TIMESTAMP(wtvdate2).
Doing it this way WILL use the appropriate table indexes.
#treznik a while ago I moved from a uts integer to a datetime or timestamp data types, for the reasons mentioned above, in that they're much easier to read and manipulate (I do quite a lot of direct table access). However I've lately started to re-think this approach for two reasons:
There is no time zone location stored, so you're inferring the time zone based on your location. This may or may not be an issue for you.
It ignores daylight saving time. So when the clocks go back at 2am, you will get 1:30am twice, and saying 2011-10-30 01:30 doesn't let you know this, whereas 1319938200 does. I don't think there's a native way in mysql to store date including time zone, except as a string (2011-10-30 01:30 BST).
I'm still trying to figure out the answer to this, myself.
Using database datetime is more efficient because every time you need to query you would need to apply from_unixtime() function to extract data from unix datetime col of the table. Using this function in where clause will completely ignore any index usage.
say my query is:
select col1,col2,colUnixdatetime from table where colUnixdatetime between wtvdate1 and wtvdate2
I would need to run:
select col1,col2,colUnixdatetime from table where From_Unixtime(colUnixdatetime) between wtvdate1 and wtvdate2
This above query will completely ignore any indexes, well there is no use of indexes here as they will never be used coz I will always have to use a function to get the real date time.
Any in-built function used on LHS of condition in a where clause would not use any indexes and if you have a HUGE table, your query will take longer.
Easier maintenance is a plus. Seeing the actual date when you do:
select * from table where ...
is pretty nice.
Easier to compare, and mysql provides a lot of date functions.