Calculate value in last months records - mysql

I have a table with customers and there power usage that's gets updated every night. I want to calculate the power usage per month.
SELECT customer, max(power_usage)-min(power_usage) AS lastmonthpower_usage FROM usage
WHERE YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
GOUP by customer
It seems like the calculation is done first on al the records per costumer in the database and then the where clause filters.
I want to filter first on the date and then calculate the power usage.

Your query looks fine (without typo on GROUP BY and escaping the keywords / reserved words of MySQL) and should give the expected result.
But you can use the month and year on the GROUP BY too. Now you should get the correct minimum and maxmium value of the year and month for calculation without WHERE. Instead you can add HAVING to filter the grouped result to the last month (or any other month):
SELECT YEAR(`date`) AS dYear, MONTH(`date`) AS dMonth, customer, MAX(power_usage) - MIN(power_usage) AS lastmonthpower_usage
FROM `usage`
GROUP BY customer, YEAR(`date`), MONTH(`date`)
HAVING dYear = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND dMonth = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
demo on dbfiddle.uk
Also make sure to avoid / dont't use keywords or reserved words of MySQL like date or usage. If you want to use keywords or reserved words in your query anyway you have to escape them with backticks (` - SELECT * FROM `usage`).

You can use a subquery
SELECT customer, max(power_usage)-min(power_usage) AS lastmonthpower_usage
from
(select * from usage
WHERE YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
)A
GOUP by customer

Related

how can i add a incremental date id to my logic? mysql

This seems really simple but i am unsure how to do it in mysql. i have a table of status changes of trades. what i would like to do is for each trade find the max date and therefore it's status in a given month. however i would like to count this trade for that month of the following month (the 1st), how can i do this in mysql?
i have below:
SELECT Trade_id,
max(Status_DateTime),
DATE_FORMAT(Status_DateTime,'%Y%m') monthyear,
DATE_ADD(DATE_FORMAT(Status_DateTime,'%Y%m'), interval 1 month) as MonthYear_increment
FROM tabletrades
WHERE trade_status in ('open','partial','partial01')
and Traade_id in('1234')
group by Trade_id,
DATE_FORMAT(Status_DateTime,'%Y%m'),
DATE_ADD(DATE_FORMAT(Status_DateTime,'%Y%m'), interval 1 month),
this does not really give me what i want though.. as the MonthYear_increment is null? i need this column as i need to be able to count my trade as the following 1st of the month.
how can i do this so that i get the following month of year as a column and i get this in the format year-month-day where day is 01. at present the date is 202005, i would ideally like 1st included too
Hmmm . . . You can get the last value for a month using row_number() and then add a month:
SELECT YEAR(status_datetime + interval 1 month),
MONTH(status_datetime + interval 1 month),
t.tradeid, t.status
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY year(Status_DateTime), month(Status_DateTime) ORDER BY Status_DateTime desc) as seqnum
FROM tabletrades
WHERE trade_status in ('open','partial','partial01') AND
Traade_id in ('1234')
) t
WHERE seqnum = 1

MySQL query to get last 12 month sales where month and year are different fields

I want to display last 12 months sales in a chart. SQL table has year and month field and not a combined date field.
Im not able to give the interval condition of 12months on Year field.
SELECT s_month,s_year,SUM(s_amount) FROM table
WHERE s_month >= Date_add(now(),interval - 12 month)
AND s_year >= Date_add(now(),interval - 12 month)
GROUP BY s_year,s_month
One method is:
select s_year, s_Month, sum(s_amount)
from t
where date(concat_ws('-', s_year, s.month, 1)) >= curdate() - interval 12 month
group by s_year, s_month;
You may want to adjust the date arithmetic, depending on whether you want the date from 12 months ago.
If you want the last 12 months in the data, you can do:
select s_year, s_month, sum(amount)
from t
group by s_year, s_month
order by s_year desc, s_month desc
limit 12;
This is a strong argument against storing date parts (month, year) in separate columns.
The WHERE clause you have does not do what you expect!
It is virtually always better to have a DATE column (or TIMESTAMP or DATETIME) and use date functions as needed to split it apart.
SELECT MONTH(dat), YEAR(dat), SUM(amount)
FROM table
WHERE dat >= CURDATE() - INTERVAL 12 MONTH
GROUP BY LEFT(dat, 7) -- eg, "2017-12"
There is another problem with your query. SUM(amount) will have a partial month at either end. I can't solve that for you without better understanding where the data comes from and when. If it is already a single reading stored on the first of the month, then no problem. If it is daily or hourly amounts, then my point stands.

MySQL (now() - Interval 1 Month) for this year only

I need some help with this.
I have the following SQL statement
SELECT * FROM table
WHERE MONTH(ORDERDATE) = MONTH(NOW() - INTERVAL 1 MONTH)
The problem is that it is returning data from last month but for all years... Am I doing something wrong or is this a normal issue that people face with this function?
The problem I am facing is that if I use the YEAR(NOW()) the report I am writing will not show the data for 2016 when we hit 2017. I'm trying to write a 6 month sales history report.
Any guidance would be appreciated.
Added Information
SELECT * FROM DATA_WH.SALESORD_HDR WHERE MONTH(ORDERDATE) = MONTH(NOW() - INTERVAL 1 MONTH)
RETURNS....
'2015-08-14 00:00:00'
Try using DATE_SUB with BETWEEN:
SELECT *
FROM DATA_WH.SALESORD_HDR
WHERE ORDERDATE BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND
DATE_SUB(NOW(), INTERVAL 2 MONTH)
This avoids the problem of having to deal with boundary conditions when using MONTH and YEAR.
Edit:
The above query will return records whose order date is between one and two months old. If you want to identify orders from the previous calendar month, then you will have to do a bit more work. Try this query:
SELECT *
FROM DATA_WH.SALESORD_HDR
WHERE ORDERDATE >= STR_TO_DATE(CONCAT('01-', LPAD(MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH)), 2, '0'), '-', YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH))), '%d-%m-%Y') AND
ORDERDATE < STR_TO_DATE(CONCAT('01-', LPAD(MONTH(NOW()), 2, '0'), '-', YEAR(NOW())), '%d-%m-%Y')
The strategy here is to build the date boundaries (August 1 and September 1 of 2016, as of the time of writing this answer), using the ORDERDATE.
Here is a Fiddle showing this logic in action:
SQLFiddle
I think you have to add another condition with AND with YEAR function
SELECT * FROM DATA_WH.SALESORD_HDR WHERE MONTH(ORDERDATE) = MONTH(NOW() - INTERVAL 1 MONTH) AND YEAR(ORDERDATE)= YEAR(NOW());
I have been working on this kind of queries recently:
This query will get the first day of the month and the last day of the month , also if you can carefully check the query you should be able to see that I have add a function from mysql that check the last day if the month "last_day(now())"
SELECT *
FROM DATA_WH.SALESORD_HDR
WHERE ORDERDATE BETWEEN date(concat(year(now()) , '-' ,month(now()) , '-01')) ,AND
date(concat(year(now()) , '-' ,month(now()) , '-' , day(last_day(now()))))
What about this?
SELECT * FROM table
WHERE MONTH(ORDERDATE) = MONTH(NOW() - INTERVAL 1 MONTH) and YEAR(ORDERDATE) = YEAR(NOW() - INTERVAL 1 MONTH)
This should only return rows where the order date is in the previous month.

How to SELECT last calender month (not the interval)?

I have date time field called transaction_date, in a report i need to select last calendar month, how do i do this ? (this should work for a month like January too)
I came up with following but this only works if the month is NOT january,
SELECT SUM(amount) AS pay_month FROM `users_payment` WHERE MONTH(transaction_datetime)= MONTH(NOW()) AND YEAR(transaction_datetime)=YEAR(NOW())
there are lot of examples using INTERVAL functions but this only select the time interval not the calendar month as i wanted too..
like
SELECT SUM(amount) AS `year_month` FROM `users_payment` WHERE DATE_ADD(NOW(), INTERVAL -1 MONTH) < transaction_datetime
but this is not what i want, i want to select sales sum of the DECEMBER only last year (remember there are other years too in the table which i dont want i.e 1979, 1981...etc)
same report next section, i need to select last 2 calender months, I dont know have any idea on how to do this too.
Have you tried the following
SELECT SUM(amount) AS `year_month` FROM `users_payment`
WHERE MONTH(DATE_ADD(NOW(), INTERVAL -1 MONTH)) = MONTH(transaction_datetime)
The above should work to show previous month; it does not distinguish between years however.
On second thought, I see what you are trying to do - To get all the transactions for a given month. Try something like this instead.
SELECT SUM(amount) AS `year_month` FROM `users_payment`
WHERE transaction_datetime BETWEEN date_format(NOW() - INTERVAL 1 MONTH, '%Y-%m-01')
AND last_day(NOW() - INTERVAL 1 MONTH)
This will list all the transactions for the previous calendar month. Alter the INTERVAL values to select multiple months.
You can try this--
SELECT SUM(amount) AS pay_month FROM `users_payment` WHERE
PERIOD_ADD(DATE_FORMAT(NOW(),'%Y%m'), -1) = DATE_FORMAT(transaction_datetime,'%Y%m')

Mysql get rows between date split between year and month columns

I have a table with a year and month in different columns, and I need to find all rows between 3 months ago and now.
SELECT * FROM `table`
WHERE DATE(CONCAT(`year`, '-', `month`, '-01')) >=
DATE_FORMAT(NOW() - INTERVAL 3 MONTH, '%Y-%m-01')
It just seems rather verbose, and possibly inefficient as this is a very large table. Is there a better way to do this?
There isn't much optimization to be had when the date is stored as separate fields, but I would re-write your query as:
SELECT *
FROM `table`
WHERE STR_TO_DATE(`year`+ '-'+ `month` + '-01', '%Y-%m-%d') >= DATE_SUB(NOW(), INTERVAL 3 MONTH)
The concatenation renders indexing on the year and month columns useless.
For more info about MySQL date functions, see: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html
Well, I had the same issue and I have figured what I think is the solution for this case.
SELECT *
FROM table
WHERE (month >= (month(curdate()) - 3 AND year >= year(curdate()))
AND (month >= month(curdate()) AND year >= year(curdate())))
Supposing you have columns named year and month.