So I have to store a particular date of the year, any year. So I will only be needing the date and month part of a date.
I can either store it with any year and just ignore it on the programming side but that feels dirty. Any better way to handle this?
Closest I could find was this one but that includes time component as well and goes on some different tangent.
If you're using MySQL >= 5.7.6, you could use a generated column. A trivial example table would look like this (untested as, ironically, I don't have access to a recent MySQL server right now):
CREATE TABLE myTable (
the_date DATE,
month_date VARCHAR(5) AS CONCAT(MONTH(the_date), '-', DAY(the_date))
);
Of course, change the generated value according to your needs (different separator, padding with zeroes on the month, etc.)
If you're stuck with an older version, you could perform a similar conversion using a view.
What is wrong with just having a DATE column value, in this example called my_date :
SELECT MONTH(my_date) AS myMonth, DAY(my_date) AS myDay, <othercolumns>
FROM table WHERE id = 1
Then you can use your PHP to get your row and output $row['myMonth'], etc.
You can also output the MONTH / DAY values as any format string you like using MySQL DATE_FORMAT .
You can also CONCAT these two values if you need them in a single column.
SELECT CONCAT(MONTH(my_date),' ',DAY(my_date)) as month_day, <othercolumns>
FROM table WHERE id = 1
Warning:
Storing dates as 0000-00-00 is perfectly valid but MySQL year 0000 is not a leap year so you can not store 0000-02-29, this will instead be saved as a default 0000-00-00.
You might as well use a default year value that is leap year safe (such as year 2k) if you're sure you're never going to use the year value. such as (2000-XX-XX).
You could store the Julian Date as an integer, and convert to Georgian Month/Day when you need it. This can keep things quite clean. Keep your eyes peeled for the leap year.
The notion of Julian here is truly, just "Day of year" and converting when needed.
function getDateFromDay($dayOfYear, $year) {
$date = DateTime::createFromFormat('z Y', strval($dayOfYear) . ' ' . strval($year));
return $date;
}
Related
I'm having a problem working with a Navicat Database. I got a column in SQL called fechaNacimiento (Birthdate) that should be a Date type, but instead it's stored as integers (most negative integers):
SELECT fechaNacimiento FROM Registrados
And I'm getting:
fechaNacimiento
-1451678400
-2082829392
-1798746192
-1199221200
-1356984000
-694299600
-1483214400
-1924976592
-1830368592
-2019670992
-1678909392
239252400
1451617200
-879541200
I don't know how this dates where loaded, I just know that inside that negative integer there's a date, and nobody here have any clue about how to spell SQL, so I have nobodoy to ask. If I just cast it to DATETIME, I get all of them as NULL values. Any idea in how to convert this data to Date type?
Numbers like that make me think of Unix times, number of seconds since 1970. If so, you might be able to do:
select dateadd(second, <column>, '1970-01-01')
This would put the negative values sometime before 1970 (for instance, -1678909392 is 1916-10-19). If you have older dates, then that might be the format being used.
These might also be represented as milliseconds. If so:
select dateadd(second, <column>/1000, '1970-01-01')
In this case, -1678909392 represents 1969-12-12.
In MySQL, you would use:
select '1970-01-01' + interval floor(column / 1000) second
I have table that contains first three columns day, month, year. I have kept it separated instead of making single column date, because this table contains information about subscription analysis. So by keeping separated I can analyze data on daywise. Now I have situation where I want to reset few data. Example like I want to reset data which day, month, year comes between date 2008-01-01 and 2010-10-01. So how can I make where condition in mysql query for separated day, month and year columns?
Please try the following...
WHERE STR_TO_DATE( CONCAT( yearValue,
'-',
monthValue,
'-',
dayValue ) ) BETWEEN '2008-01-01' AND
'2010-10-01'
This clause uses the CONCAT() function to form a string representation of the date being examined, then the STR_TO_DATE() function to convert that string to a DATE value which is then compared to the range specified.
If you have any questions or comments, then please feel free to post a Comment accordingly.
Further Reading
https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between (on MySQL's BETWEEN operator)
https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_concat (on MySQL's CONCAT() function)
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date (on MySQL's STR_TO_DATE() function)
You should really store the value as a date. But you can still do what you want. Here is one way:
where year * 10000 + month * 100 + day between 20080101 and 20101001
Note that values are all integers. A date would be better because the query could take advantage of an index.
You may concatenate your three INT columns with the TO_CHAR function. The transform that into a date using TO_DATE, and then compare.
WHERE TO_DATE(TO_CHAR(year || month || day), 'yyyymmdd') BETWEEN '20080101' AND '20100101';
I have a problem saving 'contable dates' because every month on this way has 30 days each. I need to save a element (2014-02-30) using a type date-like (not a varchar/text/blob/etc) to save this because in this project we need that. Is it possible?
Saving such a DATE "value" in a DATE or DATETIME column is possible using the sql_mode ALLOW_INVALID_DATES and no strict mode:
ALLOW_INVALID_DATES
Do not perform full checking of dates. Check only that the month is in
the range from 1 to 12 and the day is in the range from 1 to 31. This
is very convenient for Web applications where you obtain year, month,
and day in three different fields and you want to store exactly what
the user inserted (without date validation). This mode applies to DATE
and DATETIME columns. It does not apply TIMESTAMP columns, which
always require a valid date.
So checking the date for an allowed contable date could be done with triggers, since there's no other check too. I assume that for this application the 31th of each month would be an invalid date.
Example:
CREATE TABLE example (
contable_date DATE NOT NULL
) ENGINE=INNODB;
-- set the sql_mode (here for the session)
SET ##SESSION.sql_mode = 'ALLOW_INVALID_DATES';
INSERT INTO example (contable_date) VALUES ("2014-02-30");
SELECT
DAY(contable_date) as cday,
MONTH(contable_date) as cmonth,
TIMESTAMPDIFF(DAY, contable_date, '2014-03-30') as cdiff
FROM
example;
Result:
cday cmonth cdiff
-------------------
30 2 28
Demo
Using MySQL Workbench I get with
SELECT contable_date FROM example
following result:
contable_date
-------------
2014-02-30
but this doesn't work at sqlfiddle.com.
I wouldn't recommend this though, especially because one's not able to use strict SQL mode. One should consider the effect on the date and time functions too.
I know calculating age from DOB is relatively simple but I have an issue with different data entry formats in the database. Also, I know this can be easier using PHP, but I don't know PHP and only have MySQL to work with.
The DOB entered into the DB is entered as "month/day/year" or "00/00/0000". But when calculating against today's date, the date would be formatted as "year-month-day" or "0000-00-00". Furthermore, the month placed in the DOB field can have either a one number month (1/01/1999) or a two number month (01/01/1999), so it's not consistent.
I am trying to use the below to utilize CONCAT, SUBSTRING and LOCATE to output the DOB in a better suited format for the age calculation. I think I'm close but not quite there. Any help would be very much appreciated.
SELECT
CONCAT(SUBSTRING(APPU_DOB,-4,4),'-', SUBSTRING(APPU_DOB,LOCATE('/', APPU_DOB),1),'-',SUBSTRING(APPU_DOB,4,2))
FROM APPU_APP_USER
JOIN APPL_APP ON APPU_APPL_ID = APPL_ID
WHERE DATE_FORMAT(APPL_CREATE_DT, '%Y-%M-%D') >= '2014-01-01';
Instead of Concat use str_to_date function.
select str_to_date( appu_dob, '%m/%d/%Y' ) as 'dob';
on 1/01/1999 it returns a valid date formatted object with value 1999-01-01.
You can use it on other date strings that have single or two digit day or month numbers.
Note: To represent or refer a month, use small case m but not capital M, in the format pattern string.
And you should better redefine the data type of appu_dob field to date. So that you can easily apply date specific functions on it for any calculations.
I have a table.
And it has two fields id and datetime.
What I need to do is, for any two given datetimes, I need to divide the time range into 10 equal intervals and give row count of each interval.
Please let me know whether this is possible without using any external support from languages like java or php.
select ((UNIX_TIMESTAMP(date_col) / CAST((time2 - time1)/10) AS INT) + time1), count(id) from my_table where date_col >= time1 AND date_col <= time2 GROUP BY ((UNIX_TIMESTAMP(date_col) / CAST((time2 - time1)/10) AS INT) + time1)
I haven't tested it. But something like this should work.
The easiest way to divide date intervals is if you store them as longs (ie #of ticks from the "beginning of time"). As far as I know, there is no way to do it using MySQL's datetime.
How you decide to do it ultimately depends on your application. I would store them as longs and have whatever front end you are using handle to conversion to a more readable format.
What exactly do you mean by giving the row count of each interval? That part doesn't make sense to me.