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
Related
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.
I have a table like this:
I need to sum how many messages were delivered per msisdn in last 8 weeks(but for each week) from date entered. Here is what I came up with:
SELECT count(*) as ukupan_broj, SUM(IF (sent_messages.delivered = 1,1,0 )) as broj_dostavljenih,
count(*) - SUM(IF (sent_messages.delivered = 1,1,0 )) as non_billed,
SUM(IF (sent_messages.delivered = 1,1,0 )) / count(*) as ratio,
`sent_messages`.`msisdn`,
MONTH(`sent_messages`.`datetime`) AS MONTH, WEEK(`sent_messages`.`datetime`) AS WEEK,
DATE_FORMAT(`sent_messages`.`datetime`, '%Y-%m-%d') AS DATE
FROM `sent_messages`
INNER JOIN `received_messages` on `received_messages`.`uniqueid`=`sent_messages`.`originalID`
and `received_messages`.`msisdn`=`sent_messages`.`msisdn`
WHERE `sent_messages`.`datetime` >= '2016-12-12'
AND `sent_messages`.`originalID` = `received_messages`.`uniqueid`
AND `sent_messages`.`datetime` <= '2017-12-30'
AND `sent_messages`.`datetime` >= `received_messages`.`datetime`
AND `sent_messages`.`datetime` <= ( `received_messages`.`datetime` + INTERVAL 2 HOUR )
AND `sent_messages`.`type` = 'PAID'
GROUP BY WEEK
ORDER BY DATE ASC
And because I'm grouping it by WEEK, my result is showing sum of all delivered, undelivered etc. but not per msisdn. Here is how result looks like:
And when I add msisdn in GROUP BY clause I don't get the result the way I need it.
And I need it like this:
Please help me to write optimized query to fetch these results for each msisdn per last 8 weeks, because I'm stuck.
WEEK(...) has a problem near the first of the year. Instead, you could use TO_DAYS:
WHERE datetime > CURDATE() - INTERVAL 8 WEEK -- for the last 8 weeks
GROUP BY MOD(TO_DAYS(datetime), 7) -- group by week
That is quite simple, but there is a bug in it. It only works if today is the last day of a "week". And if date%7 lands on the desired day of week.
WHERE datetime > CURDATE() - INTERVAL 9 WEEK -- for the last 8 weeks
GROUP BY MOD(TO_DAYS(datetime) - 3, 7) -- group by week
Is the first cut at fixing the bugs -- 9-week interval will include the current partial week and the partial week 8 weeks ago. The "- 3" (or whatever number works) will align your "week" to start on Monday or Sunday or whatever.
SUM(IF (sent_messages.delivered = 1,1,0 )) can be shortened to SUM(delivered = 1) or even SUM(delivered) if that column only has 0 or 1 values.
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')
I have a table with columns: NAME, CHANGE_ID, and CHANGE_DATE, where each row constitutes a single change, the columns indicated who made the change(name), when it was made(timestamp), and an id for the change(integer).
I can retrieve a list of names sorted by those that have made the most changes(in the last month) with the following query:
SELECT
NAME AS name,
COUNT(DISTINCT CHANGE_ID) AS changes
FROM
CHANGE_TABLE
WHERE
DATE(CHANGE_DATE) > DATE(now() - INTERVAL 1 MONTH)
GROUP BY
name
ORDER BY
changes DESC
And I can retrieve a list of changes made per month in the last 10 months with the following query:
SELECT
DATE_FORMAT(CHANGE_DATE, '%Y-%m') AS date,
COUNT(DISTINCT CHANGE_ID) AS change_count
FROM
CHANGE_TABLE
WHERE
CHANGE_DATE > curdate() - INTERVAL 10 MONTH
GROUP BY
date
What I want is a query that will return the combined information of these queries: I want the names of the top change-makers and how many changes they have made each month for the last 10 months. I don't particularly care how the resulting table looks as long as the data is there. I have wracked my brain, but my SQL understanding is not great enough to solve the problem. Any help would be appreciated.
Have you tried grouping on date and name, something like:
SELECT
DATE_FORMAT(CHANGE_DATE, '%Y-%m') AS date,
COUNT(DISTINCT CHANGE_ID) AS change_count,
NAME
FROM
CHANGE_TABLE, (SELECT
NAME AS name,
COUNT(DISTINCT CHANGE_ID) AS changes
FROM CHANGE_TABLE
WHERE DATE(CHANGE_DATE) > DATE(now() - INTERVAL 1 MONTH)
GROUP BY name
ORDER BY changes DESC
) subq
WHERE CHANGE_DATE > curdate() - INTERVAL 10 MONTH AND change_table.name = subq.name
GROUP BY date, name
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