Calculate year difference between 2 dates with 0 year as 1 year - mysql

I have 2 dates to compare so I can count years between both date. If days is less than 365 days then I use interval to make it as 1 year. However I have problem if both date is similar in day for example 2019-10-15 to 2020-10-15 will be displayed as 2 years when I want it to be displayed as 1 year. Here is my code with not the result I want:
SELECT
TIMESTAMPDIFF(
YEAR,
'2019-10-15',
'2020-10-15' + INTERVAL 1 YEAR
) AS `year`
FROM
dob
Result:
What I want is:
2019-10-15 to 2020-10-14 = 1 year
2019-10-15 to 2020-10-15 = 1 year
2019-10-15 to 2020-10-16 = 2 year
How can I achieved that? Thanks in advance.

Does this do what you want? It seems you're only one day out from the expected output so I just subtracted a day.
SELECT
TIMESTAMPDIFF
( YEAR, '2019-10-15',
'2020-10-15'
+ INTERVAL 1 YEAR
- INTERVAL 1 DAY )
AS `year`
FROM dob

Related

MySQL Select data from table with dates between in reverse of interval 7 days

I have a MySQL requirement to select data from a table based on a start date and end date and group it by weekly also selecting the data in reverse order by date. Assume that, I have chosen the start date as 1st November and the end date as 04 December. Now, I would like to fetch the data as 04 December to 28 November, 27 November to 20 November, 19 November to 12 November and so on and sum the value count for that week.
Given an example table,
id
value
created_at
1
10
2021-10-11
2
13
2021-10-17
3
11
2021-10-25
4
8
2021-11-01
5
1
2021-11-10
6
4
2021-11-18
7
34
2021-11-25
8
17
2021-12-04
Now the result should be like 2021-12-04 to 2021-11-28 as one week, following the same in reverse order and summing the column value data for that week. I have tried in the query to add the interval of 7 days after the end date but it didn't work.
SELECT count(value) AS total, MIN(R.created_at)
FROM data_table AS D
WHERE D.created_at BETWEEN '2021-11-01' AND '2021-12-04' - INTERVAL 7 DAY ORDER BY D.created_at;
And it's also possible to have the last week may have lesser than 7 days.
Expected output:
end_interval
start_interval
total
2021-12-04
2021-11-27
17
2021-11-27
2021-11-20
34
2021-11-20
2021-11-13
4
2021-11-13
2021-11-06
1
2021-11-06
2021-10-30
8
2021-10-30
2021-10-25
11
Note that the last week is only 5 days depending upon the selected from and end dates.
One option to address this problem is to
generate a calendar of all your intervals, beginning from last date till first date, with a split of your choice, using a recursive query
joining back the calendar with the original table
capping start_interval at your start_date value
aggregating values for each interval
You can have three variables to be set, to customize your date intervals and position:
SET #start_date = DATE('2021-10-25');
SET #end_date = DATE('2021-12-04');
SET #interval_days = 7;
Then use the following query, as already described:
WITH RECURSIVE cte AS (
SELECT #end_date AS end_interval,
DATE_SUB(#end_date, INTERVAL #interval_days DAY) AS start_interval
UNION ALL
SELECT start_interval AS end_interval,
GREATEST(DATE(#start_date), DATE_SUB(start_interval, INTERVAL #interval_days DAY)) AS start_interval
FROM cte
WHERE start_interval > #start_date
)
SELECT end_interval, start_interval, SUM(_value) AS total
FROM cte
LEFT JOIN tab
ON tab.created_at BETWEEN start_interval AND end_interval
GROUP BY end_interval, start_interval
Check the demo here.

Big Query to Extract data for last one year

I need to extract data from big query for one year provided it should take data for past 12 months from last day of the last month for example todays date is 27/10/2022 .It should extract data from 01/10/2021 to 30/9/2022.
I tried WHERE DATE(xyz) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 12 MONTH) AND CURRENT_DATE().
Its taking from current date but i need it 12 months past from last day of previous month
The last day of last month can be calculated by
SELECT LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH);
+---------------------------------------------+
| LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH)) |
+---------------------------------------------+
| 2022-09-30 |
+---------------------------------------------+
To specify the beginning of the period, subtract 13 MONTH instead of 1 MONTH and add one day:
... WHERE DATE BETWEEN DATE_ADD(LAST_DAY(DATE_SUB(now(), INTERVAL 13 MONTH)), INTERVAL 1 DAY) AND LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH);

Mysql : get average grouped per week

Let's say I have a table like this:
ID Type Itemcount DateTime
1 2 4 2018-05-05
2 1 10 2019-09-09
3 2 4 2018-05-05
4 1 10 2019-09-09
How to get the average amount of items of type 1 to exist by the datetime (grouped per week)
and I should go for one year back?. What is the max amount of items?
My solution :
set #totalitemssAllTypes = (SELECT count(Itemcount)
FROM db_dev.products
where Datetime >= '2018-06-12 00:10:00.000000');
SELECT CONCAT(YEAR(Datetime ), '/',MONTH(Datetime ), '/', WEEK(Datetime )), (count(LotCount)/#totalitemssAllTypes )
FROM db_dev.products
where Datetime >= '2018-06-12 00:10:00.000000' and
Type = 1
GROUP BY WEEK(Datetime);
Please help thank you
One option would use the WEEK() function to aggregate:
SELECT
WEEK(DateTime) AS week,
AVG(Itemcount) AS item_avg
FROM db_dev.products
WHERE
Type = 1 AND
DateTime >= DATE_SUB(NOW(), INTERVAL 1 YEAR)
GROUP BY
WEEK(DateTime);
It should be noted that WEEK() may not number the weeks from 1 onward starting with the earliest week.

group by date containing certain date only

I have tried looking at some similar examples like group by date range and weekdays etc but I couldnt fix it on my query.
as per my sample data screenshot, I need to only return
sum(salesamount)/sum(salescount) for week 1
and
sum(salesamount)/sum(salescount) for week 2.
Each of the week contain 5 days (in this example is wednesday - sunday).
My Attempt:
select salesstartdate, date_add(salesstartdate, interval 5 day) as gdate,
salesamount, salescount, sum(salesamount)/sum(salescount) as ATV
from testing
group by gdate;
My desired output is:
Week 1 15.34173913
Week 2 15.80365088
Calculation to get week 1 is (3507.1+3639.97+5258.77+8417.04+5994.48)/(285+273+344+478+368)
Calculation to get week 2 is the same as above except the date would now be from 8 to 12 of June.
You can do it with a subquery. In order to first group your result set properly and then execute aggregation on it:
SELECT
concat('WEEK', ' ', weekno) as `Week #`,
MIN(salesstartdate) as startDate,
MAX(salesstartdate) as endDate,
sum(salesamount)/sum(salescount) as ATV
FROM
(
SELECT
salesstartdate,
salesamount,
salescount,
WEEKOFYEAR(salesstartdate) as weekno -- get the week number of the current year
FROM
weekno
WHERE
WEEKDAY(salesstartdate) BETWEEN 2 AND 6 -- get index of week day
) as weeks
GROUP BY
weekno
I have used 2 MySQL functions here:
WEEKOFYEAR()
WEEKDAY()
Output:
WEEK 23 | 2016-06-08 | 2016-06-12 | 15.8040
WEEK 24 | 2016-06-16 | 2016-06-19 | 15.9323
and without subquery as well:
SELECT
concat('WEEK', ' ', WEEKOFYEAR(salesstartdate)) as `Week #`,
MIN(salesstartdate) as startDate,
MAX(salesstartdate) as endDate,
sum(salesamount)/sum(salescount) as ATV
FROM
weekno
WHERE
WEEKDAY(salesstartdate) BETWEEN 2 AND 6 -- get index of week day
GROUP BY
WEEKOFYEAR(salesstartdate)
You can do this way
select SUBDATE(salesstartdate, WEEKDAY(salesstartdate)) as week_range
, sum(salesamount)/sum(salescount)
from testing
where salesstartdate between SUBDATE(salesstartdate, WEEKDAY(salesstartdate))
and date_add(SUBDATE(salesstartdate, WEEKDAY(salesstartdate)), interval 5 day))
Group by week_range

select records based on date

I have a table Employees with timestamp field createdAt and I want to run a query where I can select the employees that were created between 3 to 5 months from today date. So if
Employee A : 2016 - 01 - 28
Employee B : 2015 - 12 - 14 (less than 3 months from today)
Employee C : 2015 - 9 - 11 (more than 3 months but less than 5 months from today)
Employee D : 2015 - 01 - 20 (more than 5 months from today)
then my query should return only Employee C.
So far I have come up with this.
SELECT *
FROM employees
WHERE createdAt > NOW() - INTERVAL 2 Months AND createdAt < NOW() - INTERVAL 5 Months
start with lower date to higher. you can try this:
SELECT * FROM employees WHERE date(createdAt) between DATE_SUB(NOW(), INTERVAL 5 MONTH) and DATE_SUB(NOW(), INTERVAL 3 MONTH)