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);
Related
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.
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
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
I have a data like this:
And now i want to print this data on weekly basis like this
+------------+-----------+
| weeks | sum(count)|
+----------- +-----------+
| week 1 | 2526 |
| week 2 | 26987 |
+------------+-----------+
This query sum all mimi_count but i want data in above figure format may be it has to with
group by
.I have searched a lot but could't find what i want
SELECT sum(mimie_count) as mimie
FROM statistics
WHERE mimiDate > DATE_SUB(NOW(), INTERVAL 1 WEEK)
SELECT
WEEK(mimiDate) weeks,
sum(mimie_count) as mimie
FROM statistics
WHERE mimiDate > DATE_SUB(NOW(), INTERVAL 5 WEEK)
GROUP BY WEEK(mimiDate)
ORDER BY mimiDate;
Note: If you want last X weeks sum week wise then use this DATE_SUB(NOW(), INTERVAL X WEEK). Also note that WEEK function assumes the start of the week is Monday
EDIT:
If you want the first column like you stated then you need to adopt the following query:
SELECT
CONCAT('week ',WEEK(mimiDate)) weeks,
sum(mimie_count) as mimie
FROM statistics
WHERE mimiDate > DATE_SUB(NOW(), INTERVAL 5 WEEK)
GROUP BY WEEK(mimiDate)
ORDER BY mimiDate;
For Specific date range search:
SELECT
CONCAT('week ',WEEK(mimiDate)) weeks,
sum(mimie_count) as mimie
FROM statistics
WHERE mimiDate BETWEEN '2016-01-21' AND ' 2016-03-05'
GROUP BY WEEK(mimiDate)
ORDER BY mimiDate;
I have an app that inserts a Unix timestamp on registration. What I'd like to do, is calculate usage details for the month since the last monthly anniversary day. So I would need a unix timestamp of what the most recent anniversary day would be.
For example, if a registration is submitted on January 5, the customer's anniversary day is the 5th. So to check usage on February 15th, I need to retrieve all entries from the logs since Feb 5.
Getting the day of registration is easy:
SELECT DATE_FORMAT(FROM_UNIXTIME(created), '%d') FROM accounts
however, I'm lost finding the unix timestamp of the last anniversary date based on the registration day. How would I do that? To clarify, I'm looking to return all action_id created on or after the most recent anniversary date.
Tables:
accounts
+------------+------------+
| account_id | created |
+------------+------------+
| 1 | 1321838910 |
+------------+------------+
....
logs
+------------+------------+------------+
| account_id | action_id | created |
+------------+------------+------------+
| 1 | 233 | 1348249244 |
+------------+------------+------------+
| 1 | 263 | 1348257653 |
+------------+------------+------------+
....
Note: to keep things simple, I'm going to forgo figuring out what happens if an anniversary day is the 31st for example - that is, unless someone has a super ninja statement that takes those occurrences into account.
Not tested. See what you think. Logic is to:
Get the last day of the current month.
Add the account created day number of days to #1 result.
If current day is greater than created day, subtract 1 month from #2 result. Else subtract 2 months.
SELECT l.*
FROM accounts a
LEFT JOIN logs l
ON a.account_id = l.account_id
AND l.created >= UNIX_TIMESTAMP(
DATE_SUB(DATE_ADD(LAST_DAY(NOW()), INTERVAL DAY(FROM_UNIXTIME(a.created)) DAY),
INTERVAL IF(DAY(NOW()) > DAY(FROM_UNIXTIME(a.created)), 1, 2) MONTH));
Edit
I gave this some more thought and perhaps the query below will work regardless of when the anniversary date is. Assumption I made that if the anniversary day is not in a particular month then last day of the month should be taken. It's ugly but I put in some variables to make it more concise, there must be a nicer way. Anyway, I haven't tested but logic as follows.
If current day > anniversay day then just subtract the difference in days to get date.
else if the last day of the previous month is less than anniversary day then use the last day of previous month.
else subtract the day difference between anniversary day and last day of previous month from last date of previous month.
SELECT l.*
FROM accounts a
JOIN logs l
ON a.account_id = l.account_id
AND l.created >= UNIX_TIMESTAMP(
IF(#dNow := DAY(NOW()) >= #dCreated := DAY(FROM_UNIXTIME(a.created)),
DATE_SUB(NOW(), INTERVAL #dNow - #dCreated DAY),
IF(DAY(#endLastMonth := LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH))) <= #dCreated,
#endLastMonth,
DATE_SUB(#endLastMonth, INTERVAL DAY(#endLastMonth) - #dCreated DAY))));
Perhaps this using order by desc to get most recent created date?
SELECT DATE_FORMAT(FROM_UNIXTIME(X.created), '%d')
FROM (
SELECT CREATED
FROM mytable
WHERE ACCOUNT_ID = ? -- customer id
AND DATE_DIFF(DATE_FORMAT(FROM_UNIXTIME(CREATED),'%Y-%m-%d'), NOW()) MOD 30 = 0
AND DATE_DIFF(DATE_FORMAT(FROM_UNIXTIME(CREATED),'%Y-%m-%d'), NOW()) / 30 = 1
ORDER BY CREATED DESC LIMIT 1)X;