This is my MySQL Query to return the age from the date of birth
SELECT
PensionerDOB,
YEAR( CURDATE() ) AS Year,
DATE_FORMAT( STR_TO_DATE( PensionerDOB, '%d-%M-%Y' ), '%Y') AS age,
YEAR( CURDATE() ) - DATE_FORMAT( STR_TO_DATE(`PensionerDOB`, '%d-%M-%Y' ), '%Y' ) AS differenage
FROM
`pensionerbasicdata`
The query is executed. But it returns the age difference is in a negative value.
SELECT *,
TIMESTAMPDIFF(year, STR_TO_DATE(CONCAT(SUBSTRING_INDEX(PensionerDOB, '-', 2), '-19', SUBSTRING_INDEX(PensionerDOB, '-', -1)), '%d-%M-%Y'), CURRENT_DATE) AS age
FROM pensionerbasicdata
The problem with 2-digit year fixed - all years are treated as 19xx.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f356258c99b20d13b0c4e2349b801f18
Try this one it will work,
Query,
SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(now(),YourDateofBirth)), '%Y')+0 AS Age from AgeCalculationFromDatetime
here Mysql is not parsing two-digit years as expected.. Instead of 1945- it's returning 2065,1953- it's returning 2053.
Please follow this link to parse the date with two digits years.
how-to-use-str-to-date-mysql-to-parse-two-digit-year-correctly
Related
I am trying to make simple MySQL query to display upcoming birthdays using below query. How to exclude/remove previous(yesterday) day from showing.
CREATE TABLE users (
name VARCHAR(100),
birthday DATE
);
INSERT INTO users (name, birthday) VALUES
('kostas', '1983-10-08'),
('kostas', '1983-10-11'),
('yannis', '1979-10-13'),
('natalia', '1980-10-15'),
('kostas', '1983-10-12'),
('Moskas', '1978-10-14'),
('Rasman', '1978-10-13'),
('natalia', '1980-10-18'),
('natalia', '1980-10-16');
Query:
SELECT *
FROM
users
WHERE
birthday != '' AND ABS(DAY(CURDATE()) - DAY(birthday)) < 2
ORDER BY
DAY(birthday)
Demo: sqlfiddle
You have to use BETWEEN instead of ABS. The absolute value do not return what you want, the between 0 and "days before the birthday" (2) is the right way to get days until birthday.
You also have to use DAYOFYEAR instead of DAY and you have to reverse the order of the subtraction terms DAYOFYEAR(birthday) - DAYOFYEAR(CURDATE())
To workaround leap years birthdays, as suggested here, birthday year should be converted to current year with:
DAYOFYEAR(DATE_ADD(e.birthdate, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR))
The final SQL is:
SELECT *
FROM
users
WHERE
birthday != '' AND (DAYOFYEAR(DATE_ADD(birthday, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR))-DAYOFYEAR(CURDATE())) between 0 and 2
ORDER BY
DAY(birthday)
I'd do it this way:
Transfer the birthdays to the current year and then define the datediff you want:
SELECT *,
DATEDIFF(str_to_date(CONCAT(YEAR(curdate()), '-', MONTH(birthday), '-', DAY(birthday)), '%Y-%m-%d'), curdate()) AS `days until birthday`
FROM users
WHERE DATEDIFF(str_to_date(CONCAT(YEAR(curdate()), '-', MONTH(birthday), '-', DAY(birthday)), '%Y-%m-%d'), curdate()) BETWEEN 1 AND 5 ;
I have used this previously, hope it will help others.
SELECT name, birthday, DATE_ADD(birthday, INTERVAL IF(DAYOFYEAR(birthday) >= DAYOFYEAR(CURDATE()), YEAR(CURDATE())-YEAR(birthday), YEAR(CURDATE())-YEAR(birthday)+1) YEAR ) AS next_birthday
FROM users
WHERE birthday!= '' AND disabled = '0'
HAVING next_birthday BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 3 DAY)
ORDER BY next_birthday
SELECT month,Avg(rain_fall) FROM rain_fall WHERE
STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y')
between
STR_TO_DATE('01-Jan-1991','%d-%b-%Y') and
STR_TO_DATE('01-Dec-1993','%d-%b-%Y')
group by month
order by MONTH(STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y'))
UNION
SELECT month,Avg(data_value) FROM temprature_data WHERE
STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y')
between
STR_TO_DATE('01-Jan-1991','%d-%b-%Y') and
STR_TO_DATE('01-Dec-1993','%d-%b-%Y')
group by month
order by MONTH(STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y')) ;
The above is my sql query. I want to get the average value against all months in a year of temprature_data table and rain_fall table for the selected years.
The error message received:
#1221 - Incorrect usage of UNION and ORDER BY
Use Parenthesis on each select query and UNION ALL:
P.S.: month is a reserved word. If here, you're using it a column name, try to change it to something else so it may not make a conflict in your later queries. Check this list of reserved words in MySQL
(SELECT
month,
Avg(rain_fall)
FROM
rain_fall
WHERE
STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y')
between
STR_TO_DATE('01-Jan-1991','%d-%b-%Y')
and
STR_TO_DATE('01-Dec-1993','%d-%b-%Y')
group by
month
order by
MONTH(STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y'))
)
UNION ALL
(
SELECT
month,
Avg(data_value)
FROM
temprature_data
WHERE
STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y')
between
STR_TO_DATE('01-Jan-1991','%d-%b-%Y')
and
STR_TO_DATE('01-Dec-1993','%d-%b-%Y')
group by
month
order by
MONTH(STR_TO_DATE( CONCAT('01','-',month,'-',year) , '%d-%b-%Y'))
);
I want to get count of all assessments in past three months. So this should count for current and previous two months as separate
like Count1 50 for this month
Count2 100 for one month back
Count2 50 for two month back
SELECT Count(AssessmentID)
from AssessmentListing
WHERE (STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >=
DATE_FORMAT(NOW(), '%Y' ))
You should not be storing dates as strings. If you want the current month and two months back, then something like this:
SELECT DATE_FORMAT(STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p'), '%Y-%m') as yyyymm,
Count(*)
from AssessmentListing
WHERE STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >= DATE_SUB(DATE_SUB(CURDATE(), INTERVAL 1 - DAY(CURDATE()), INTERVAL 2 MONTH)
GROUP BY yyyymm;
I am not sure what your WHERE clause actually does. But comparing a string and a date is probably not what you really want.
Like #Jarlh mentioned in comment you can use Extract function to extract the month from the date column and group the result using that.
select EXTRACT(MONTH FROM AssessmentSubmittedDatetime) as _month,
Count(AssessmentID)
from AssessmentListing
WHERE (STR_TO_DATE(`AssessmentSubmittedDatetime`, '%d-%b-%Y %I:%i %p') >=
DATE_FORMAT(NOW(), '%Y' ))
group by _month
I'm looking for a solution for my statistical problem:
I have a table with one date column in it. Now what I want to do is count the number of rows in a certain time interval of 10 seconds:
SELECT count(id), ... AS interval WHERE ... GROUP BY interval
Anybody an idea how I can perform this?
Thanks,
Markus
SELECT
CONCATENATE(
SUBSTR(
DATE_FORMAT(yourtimestamp, '%Y%m%d%H%i%s')
, 1, -1)
, 0) AS time_bin,
COUNT(*)
FROM yourtable
WHERE ...
GROUP BY CONCATENATE(
SUBSTR(
DATE_FORMAT(yourtimestamp, '%Y%m%d%H%i%s')
, 1, -1)
, 0)
(use str_to_date() to convert back to a timestamp)
or...
SELECT FROM_UNIXTIME(
10*FLOOR(UNIX_TIMESTAMP(yourtimestamp)/10)
) AS time_bin,
COUNT(*)
FROM yourtable
WHERE ...
GROUP BY FROM_UNIXTIME(
10*FLOOR(UNIX_TIMESTAMP(yourtimestamp)/10)
)
Given:
Start Year
Start Month & Start Day
End Month & End Day
What SQL statement results in TRUE if a date lands between the Start and End days? The problem is in finding the end year so as to get a start_date and an end_date.
Maybe convert the dates to UNIX timestamps? Then it would be simple less-than or greater-than integer arithmetic.
Do you really need true/false values, or can you just SELECT? Assuming $date contains the date you're looking for in 'yyyy-mm-dd' format:
SELECT * FROM mytable WHERE $date > start_date AND date < end_date;
Having the year in a separate field also works, but looks uglier and probably kills performance:
SELECT * FROM mytable WHERE $date > CONCAT(year, '-', start_date) AND
$date < CONCAT(year, '-', end_date);
And with handling for the end < start case:
SELECT * FROM mytable WHERE $date > CONCAT(year, '-', start_date) AND $date <
IF(start_date < end_date,
CONCAT(year, '-', end_date),
DATE_ADD(CONCAT(year, '-', end_date), INTERVAL 1 YEAR));
One way to calculate the end year (so as to derive the end_date):
end_year = start_year +
greatest( -1 *
sign(
datediff(
date(
concat_ws('-', year, end_month, end_day )
),
date(
concat_ws('-', year, start_month, start_day )
)
)
), 0
)