retrieving items from table that fall between a date range.
the date (db table field name is called: submission_date) is being stored in the database as d-M-y (ex: 21-Dec-10)
This is being stored in an oracle database, as sysdate. (it needs to stay in the database as that format, so changing the format of how it is stored is not an option)
I want to convert 21-Dec-10 to 20101221, so I can compare it to date the user has posted, which are two values, end_date, begin_date
All I need is to properly convert submission_date to Ymd (20101221)
below is in theory what I want to do:
select
*
from
table
where
(convert(Ymd=>submission_date) >= $begin_date
AND
convert(Ymd=>submission_date) <= $end_date)
If the column submission_date is of DATE datatype and $begin_date and $end_date are strings of yyyymmdd format then you could use the following query to retrieve rows that fall between a date range:
SELECT *
FROM tab
WHERE submission_date BETWEEN
TO_DATE ( $begin_date, 'yyyymmdd') AND
TO_DATE ( $end_date, 'yyyymmdd');
By not applying a function on submission_date, we give Oracle a chance to use an index on that column, if an index exists.
When you said,
This is being stored in an oracle database, as sysdate.
To me that's saying that the datatype of the column is DATE.
First let's disabuse you of the notion that DATE is stored in a String FORMAT inside Oracle. This is completely erroneous.
If the datatype of the column is DATE then the actual value is stored using 7bytes but can be thought of as a number. The fact that when you query it to examine the value you see a dd-mon-yy format is a function of NLS settings or client options. Remember Oracle is a server, any tool that let's you look at the information stored there is a portal to that info. In other words, you're not really looking at the data, you're looking at something that went and got the data and then put it on the screen for you to see. make sense?
Ok so now that you know there's no such thing as DATE's stored in a certain format, DATE MATH becomes simple.
SELECT Submission_date FROM tab
Returns a date formatted as a string based on client settings or NLS settings.
SELECT Submission_date - 1 FROM tab
Returns a date which is the same time of day, one day earlier
Notice I didn't have to do crazy things to the number 1 to perform date math and that's because the date datatype supports math processing that works like it's a number so subtraction is a simple thing.
If your variables of $begin_date are passed to Oracle as dates then they too need nothing done to them because again, they can be used like numbers.
WHERE Submission_date BETWEEN $Begin AND $End will work.
Bonus Material
BETWEEN is inclusive on both ends.
More Bonus Material
A date is actually stored like this:
Byte 1 -> Century
Byte 2 -> Year
Byte 3 -> Month
Byte 4 -> Day
Byte 5 -> Hour
Byte 6 -> Minute
Byte 7 -> Second
This allows for extremely broad ranges of dates to be supported. It's really the date math library that can make that datatype do cool things like add leap years and get the conversion from Julian to Gregorian and such.
Bonus Material Redux
SQL Server stores dates as two 4 byte integers packed together into a BINARY(8). The first 4-bytes are the elapsed days since SQL Server's base date of 1/1/1900. The Second 4-bytes Store the Time of Day Represented as the Number of Milliseconds After Midnight in quanta of 3.33 milliseconds.
It's a mistake to assume that if the value can be stored, the RDBMS supports it. I believe that SQL Server doesn't handle BC dates at all nor does it handle dates well into the future a la the year 9999. MSSS2008 did introduce a new datatype to deal with those large dates.
Related
I have a mysql table that has a column with date type.
I'm going to store non-Gregorian date in this column (i.e. Jalali date).
I tested this by using phpMyadmin and storing a Jalali date and no error happend.
Is it a good idea to store non-Gregorian dates in date type?
If not; which is better? storing it as varchar or as timestamp or timestamp as Int or something else?
Is it a good idea to store non-Gregorian dates in date type?
No. Aside that some valid date in one calendar system doesn't exist in another calendar, functions working on DATE typed columns may not work properly. The matter is not just storing data, you need to process this data and for example compare them with CURDATE().
storing it as varchar or as timestamp or timestamp as Int or something else?
If you choose a proper formatting, use two digits for month and day and static number of digits for year, a character string type, CHAR or VARCHAR is fine. Comparing theme against each other is just a lexical comparison and you still can write your functions o procedures to extend functionality.
Choosing TIMESTAMP or DATE changes the question as former represents a specific time but latter represents a specific entry in calendar. If you want put time beside date they still differ in meaning. You should think about issues like daylight-saving time changes which cause some people prefer to put calendar entry (DATE) and some prefer seconds passed from 1 Jan 1970 (TIMESTAMP). e.g. there is two timestamps for 1393-06-30 23:30:00 in Hijri Shamsi calendar based on current Iran government laws.
You can store non-gregorian dates in an integer field in the database.
Examples:
year:1396, month:11, day:17 => 13961117
year:1393, month:4, day:9 => 13930409
by using this, you can query rows to find a specific date and dates that are <=> than a specific date, but unfortunately, you can't compare them against each other.
Internal storage and binary interface of almost all database systems have nothing to do with calendars. you just store date (and possibly time) into database, providing no calendaring information. It's only a simple number of days, seconds or milliseconds past from a specific point in time (usually midnight 1970-01-01).
So you just need to provide an API abstraction of dates in your application layer. Everything else will work. You convert all your dates to Gregorian or Unix timestamp, and send queries to MySQL as usual.
Non Gregorian calendar still operate by Year, Month, Day and Time so it can be stored in 4 separate columns like:
CREATE TABLE `Calendar` (
`Year` int,
`Month` tinyint,
`Day` tinyint,
`Time` time
);
I make possible to store dates without conversion and permit group by Year and Month
I'm using the following SQL query in postgres:
SELECT
date_trunc('month', s.thedate),
r.rank,
COUNT(r.rank)
FROM
serps s
LEFT JOIN ranks r ON r.serpid = s.serpid
GROUP BY
date_trunc('month', s.thedate), s.thedate, r.rank
ORDER BY
s.thedate ASC;
when I run that query directly against the database, I get the data all the data I need and the dates seem to be correct (formatted in Y-m-d g:i:s).
However, when I run it with PHP, Postgres instead of the date returns the timestamp.
Therefore, when I use that timestamp in PHP date, the whole date is incorrect.
For instance:
The first row Postgres displays it as:
"2013-08-01 00:00:00, 36, 1"
but PHP receives:
"1375315200000, 36, 1"
When I try to do:
echo date("Y-m-d", 1375315200000);
The output is:
45552-01-02
instead of
2013-08-01
At first I thought it was a padding issue, perhaps? I dropped the last three zeros in the timestamp so:
echo date("Y-m-d", 1375315200);
and that returns:
2013-07-31
My questions are:
1) Is it only a coincidence that after dropping three zeros, the timestamp represent a day before the actual date stored in the database?
2) Why Postgres interprets the timestamp correctly; whereas php doesn't? According to the documentation Postgres timestamp should be in the unix timestamp format.
The number they're returning is milliseconds in the Unix era, rather than seconds. Dividing by 1000 before feeding it to PHP is necessary.
With databases, be careful to check whether their timestamp is actually UTC/GMT, or has been offset to the server's timezone. I've seen both done. My server, located in California, is Pacific Time for MySQL timestamps. Be careful about sticking PHP timestamps into the database and then formatting with SQL, or vice-versa.
While creating a table, I defined one column of DATE type and one of TIME type. As I insert the values using a php script like :
date--> 2013-11-11
time--> 12:12:12
and when I query the sql browser I see those values in exactly the same manner. But I am unaware of the format with which it stores the date and time. Like yyyy-mm-dd or yyyy-dd-mm.
Is there any way I change it ?
Dates and times are stored in MySQL in the format "YYYY-MM-DD" and "YYYY-MM-DD HH:MM:SS" which is not necessarily the format you want to display in your web page or application. There are two methods to reformat the date and time into the desired format. One is to do it in the SQL query in MySQL calling the DATE_FORMAT() function and the other is to do it with the programming language retrieving the data from the MySQL database.
From MySQL 5.1:
The DATE type is used for values with a date part but no time part.
MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The
supported range is '1000-01-01' to '9999-12-31'.
For second question: you can't change default DATE format for the storage, please see this question also
http://dev.mysql.com/doc/refman/5.5/en/datetime.html
MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format
http://dev.mysql.com/doc/refman/5.5/en/time.html
MySQL retrieves and displays TIME values in 'HH:MM:SS' format
I do not believe this can be changed. But you do not care. You can extract dates and times in the format of your liking with the DATE_FORMAT() and the TIME_FORMAT() functions.
If you want to know the internal storage of Date columns, you can check Date and Time Data Type Representation, but I think you want to select date in different format; which other guys already answered about it.
It is stored in 3 bytes, and it is always YYYY-MM-DD.
The datetime is in Y-m-d H:i:s format, or year month day and hour minute second. If you only use a part, the format stays the same.
If you want to change the format there are many ways. The easiest would be to do something like return date("Y-d-m H:i:s", strtotime($mysqldatetime)); (will turn it to dutch date);
Keep in mind that you are using two seperate columns, one for time and one for the date. If you use only one column the missing values are filled with default values (time would be 00:00:00 and date would be 1970-01-01
I'm trying to store a week schedule (e.g. Monday, 9am-5pm, etc.). I do not have the need to store the dates; I just need to save the following: day, from time, to time.
So, say I have the following time values:
1:20pm
1320
8:00 AM
etc
Assuming that the values are actual valid times, how do I convert these strings into MySQL Time type? And how do I do the reverse? (I'm using PHP.)
Also, how do I query for something like this: find every store that is open on Mondays between 2pm and 3pm? Do I just do something like: WHERE day = 1 AND from_time >= 2pm AND to_time <= 3pm (changing '2pm' and '3pm' to whatever their converted values are, of course)? Or is there some MySQL function better suited for such queries?
MySQL has built in conversion for unix timestamps to a MySQL date:
INSERT INTO table (the_date) VALUES (FROM_UNIXTIME(your_timestamp));
…and the other way around…
SELECT UNIX_TIMESTAMP(the_date) FROM table;
You can use the DAY() and DAYOFWEEK() functions in your WHERE conditionals to convert your MySQL timestamps into the relevant units for you to do your query.
You might need to play around a bit with your schema to determine the best structure to allow you to get the functionality you need here. E.g. it might not make sense to store the day-of-week in a datetime field at all.
MySQL has a TIME data type - it will store values in the hh:mi:ss format, and you can use the TIME_FORMAT function to change the presentation to however you'd like.
Try not to rely on functions applied to the column for comparison - IE:
WHERE TIME_TO_SEC(column) = 123
...because it will render an index, if one exists on the column, useless -- ensuring a table scan (worst performing option).
MySQL understands the ISO 8601 date format, so you have to give time in the form "08:00:00" for 8:00 AM.
You can just use a string with a valid ISO 8601 time in your WHERE clause.
http://en.wikipedia.org/wiki/ISO_8601
http://dev.mysql.com/doc/refman/5.1/en/time.html
http://dev.mysql.com/doc/refman/5.1/en/datetime.html
I want to store dates in mysql so I set the table to be of type 'Date', which is fine but mysql requires that the full date is provided YYYY-MM-DD.
However some of my data does not include day and some is missing the month. Now I could just use a varchar(10) field, but then its difficult to run date based queries on the data.
Is there another date format which is not as strong and would allow me to use ?? or 00 where the day/month is not known?
Following from Babiker's answer, this is what the documentation says:
Ranges for the month and day specifiers begin with zero due to the fact that MySQL allows the storing of incomplete dates such as '2014-00-00'.
You can replace with zeros.