MySQL: Modifying output of a field for calculation - mysql

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.

Related

Extract Numeric Date Value from short Date Format in SQL

I am trying to convert short date format to numeric date format in SQL.
Here are the dates I am trying to convert:
16-Mar-20
18-Mar-20
12-Mar-20
I have seen many methods to re-format dates based on numeric numbers but I am working with a dataset which has varied date-types. To ensure smoothness, I wanted to know what's the way to convert these numbers to numeric date. Note that even if I extract the day month and year individually I could multiply them with respective values to get the dates. Here's what I have done: (Although I have tried multiple things but this is the one which has yielded me the closest result, Note that my end goal is to convert the date into numeric value)
FROM_UNIXTIME(`Start Date`, 'dd-MMM-yy') AS 'Date Numeric'
Here Start Date is formatted in the way I have mentioned above. (14-Mar-20).
UNIX_TIMESTAMP is what you need, but first you have do transform your data to a Date
UNIX_TIMESTAMP(STR_TO_DATE(`Start Date`, '%d-%b-%y'))
With
SELECT UNIX_TIMESTAMP(STR_TO_DATE( "14-Mar-20", "%d-%b-%y"))
You get
UNIX_TIMESTAMP(STR_TO_DATE( "14-Mar-20", "%d-%b-%y"))
1584144000
If you want the Unix timestamp, use UNIX_TIMESTAMP():
UNIX_TIMESTAMP(STR_TO_DATE(`Start Date`, 'dd-MMM-yy'))

MySQL Query Group By Date

I have tried various recommendations based off of other posts with no avail.
I have a database scheme of records with a Created_Date Key, and Value would be 01/01/2017
I am trying to query the database records to give a returned count of How many records per month and which month those fall in line with.
With the following
SELECT SQL_NO_CACHE MONTH(`Created_Date`), COUNT(*)
FROM `CRM_Leads`
GROUP BY MONTH(`Created_Date`)
I return
MONTH(`Created_Date`) COUNT(*)
NULL 872
I have also tried almost all the variations on the following post
Count records for every month in a year
Any help would be appreciated.
assuming your created_date is a string of format ('dd-mm-yyyy') the you should convert as date with str_to_date
SELECT SQL_NO_CACHE MONTH(str_to_date(`Created_Date`, '%d/%m/%Y')), COUNT(*)
FROM `CRM_Leads`
GROUP BY MONTH(str_to_date(`Created_Date`, '%d/%m/%Y'))
For as long as you store date/time information as strings, you will have great difficulty using any date/time specific functions and features. If you are getting NULL from MONTH(str_to_date(Created_Date, '%d/%m/%Y')) then the str_to_date isn't converting the strings to dates and the most likely reason for this is the d m y "pattern" is not corrrect.
All you have old us about your "strings that might be dates" is that one of them looks like this: 01/01/2017. Now that could be DD/MM/YYYY or MM/DD/YYYY and we simply cannot tell which one is correct from the single value you have chosen to share with us. Look for any day value greater then 12 in your data e.g. 17/01/2017 ==> DD/MM/YYYY or 01/17/2017 ==> MM/DD/YYYY
Once you have made the choice of which pattern your "strings that might be dates" follow; apply that pattern in the str_to_date() function. You migh want to try a few different patterns to get the best one (and these are just 3 of many you could try):
# which pattern is best for you?
SELECT Created_Date
, str_to_date(`Created_Date`, '%d/%m/%Y') "d/m/y"
, str_to_date(`Created_Date`, '%m/%d/%Y') "m/d/y"
, str_to_date(`Created_Date`, '%Y-%m-%d') "y-m-d"
FROM `CRM_Leads`
You will not have success with your group by query until you choose the most appropriate d m y pattern to apply in teh str_to_date function. Note here that you might also have a variety of patterns in your data, in which case you have an even bigger problem to solve.
Once you have made the choice of which pattern your "strings that might be dates" follow; apply that pattern in the str_to_date() function and ONLY THEN your group by query will work.

How can i do a count of two columns in mysql?

i want to do a count of two columns in mysql. One of the columns is a string but another is a date like 06/08/2017 and when i do my query i get 0 results.
SELECT count(*) FROM `castigos` WHERE inicio_normal=05/06/2017 AND cod_emplazamiento=1
I have entries of that data but its dont show me anything. Maybe the type of data in the date is wrong?
What should i do?
Add the date field to your select and group by it. Otherwise mysql extensions doesn't recognize you want to group by the date and will aggregrate all the results into 1 column. And since you are getting 0 count, you're where clause must not be working.
Your date format seems malformed. usually YYYY/MM/DD format (standard format);
or specify a format using SELECT STR_TO_DATE('17/09/2010','%d/%m/%Y');
MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The supported range is '1000-01-01' to '9999-12-31'.
the below uses the implicit casting and default date format to convert the string date to a valid date.
SELECT inicio_normal, count(*)
FROM `castigos`
WHERE inicio_normal='2017/05/06'
AND cod_emplazamiento=1
GROUP BY inicio_normal
Otherwise its doing math and comparing that date to the number stored for the date.
Understand dates should be stored in a date datatype and when you query dates you're passing in a string that is being cast to a date datatype for comparison. So you need to use the standard format, or cast your string to a date so the db engine knows how to convert your format to a date.
Try this :
SELECT count(*) FROM `castigos` WHERE inicio_normal="05/06/2017" AND cod_emplazamiento=1 GROUP BY inicio_normal
WHERE inicio_normal=05/06/2017
If you divide 3 by 6 then by 2017 you get a very small value indeed. OTOH if you reformat this as a date (e.g. 20170605, if you gave us a European formatted date - dd/mm/yyyy) then your query will find the rows you showed us.

Database check condition with day,month,year columns

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';

Best way to store date and month only in MySQL

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;
}