MySQL Query for getting payments evolution graph during latest 12 months - mysql

My app stores payments done by clients. At the end of every month, the total paid that month is calculated and given to owner: I have a payments table that has the following fields (the most important).
id, datepaid, endingdate (actual month's closing date), ammount, type, code, ...
Now, having a year of payments, I've been asked to create a graph of payments evolution (totals) of latest 12 months.
By reading, etc. this is the query I've got, but I don't know how to get the latest 12 months totals (and to get 0 in case no payment was done that month)....
SELECT id, endingdate, datepaid, SUM(ammount) AS total
FROM `sis_payments`
WHERE endingdate >= DATE_SUB( CURDATE( ) , INTERVAL 1 YEAR )
GROUP BY endingdate
I know it may be badly designed, but it's what I was given... any clues? Thanks

You could try GROUP BY YEAR(endingdate), MONTH(endingdate), or something equivalent using DATE_FORMAT. Take a look at the Mysql documentation for DATE_FORMAT.
Also, don't include the date fields (endingdate, datepaid) in the SELECT clause. Instead, use YEAR(endingdate), MONTH(endingdate), just like in GROUP BY.
Getting 0 when there were no payments that month is a little more complicated in SQL. You could handle that in PHP, after running the query.
UPDATE
Example using DATE_FORMAT:
SELECT
DATE_FORMAT(mrendido,'%y-%m') as xyearmonth,
SUM(FORMAT(ammountpaid,2)) AS ammtotal
FROM sis_pyments
WHERE mrendido >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)
GROUP BY xyearmonth
ORDER BY xyearmonth ASC

Related

How to sum month in Google Big Query?

I am using Google Big Query and I am trying to to sum the data from each month (which was given on a daily basis).
SELECT sum(EXTRACT(MONTH FROM date)) as month, region_name, avg(stringency_index) as stringency_index, sum(deaths) as deaths FROM `bigquery-public-data.covid19_govt_response.oxford_policy_tracker`
WHERE (stringency_index is not null) and (region_name = "New York" OR region_name = "Florida") AND (date BETWEEN '2020-05-01' AND '2020-12-30')
GROUP BY region_name, date
ORDER BY EXTRACT(MONTH FROM date);
But it still is showing 30ish rows for each month, making me believe that it isn't summing the months, but still giving me the data by data. Would I use a TRUNC function? The problem is the column label for date in this dataset is date, so I don't know how to TRUNC(MONTH as date) if date is both a column name and a variable.
Any help is appreciated.
Thank you,
Yoni
First, I would recommend truncating the date. Then:
SELECT date_trunc(date, month) as month, region_name,
avg(stringency_index) as stringency_index,
sum(deaths) as deaths
FROM `bigquery-public-data.covid19_govt_response.oxford_policy_tracker`
WHERE stringency_index is not null and
region_name IN ('New York', 'Florida') AND
date BETWEEN '2020-05-01' AND '2020-12-30'
GROUP BY region_name, month
ORDER BY month;
The problem with your query is that you are aggregating by date. You could fix it by aggregating by month; I think the complete date is safer -- although COVID data has not yet existed for an entire year, so right now, you don't have to worry about data from months in different years.

create a ranking and statistics with repeated database records

Today I want to get a help in creating scores per user in my database. I have this query:
SELECT
r1.id,
r1.nickname,
r1.fecha,
r1.bestia1,
r1.bestia2,
r1.bestia3,
r1.bestia4
r1.bestia5
FROM
reporte AS r1
INNER JOIN
( SELECT
nickname, MAX(fecha) AS max_date
FROM
reporte
GROUP BY
nickname ) AS latests_reports
ON latests_reports.nickname = r1.nickname
AND latests_reports.max_date = r1.fecha
ORDER BY
r1.fecha DESC
that's from a friend from this site who helped me in get "the last record per user in each day", based on this I am looking how to count the results in a ranking daily, weekly or monthly, in order to use statistics charts or google datastudio, I've tried the next:
select id, nickname, sum(bestia1), sum(bestia2), etc...
But its not giving the complete result which I want. That's why I am looking for help. Additionally I know datastudio filters where I can show many charts but still I can count completely.
for example, one player in the last 30 days reported 265 monsters killed, but when I use in datastudio my query it counts only the latest value (it can be 12). so I want to count correctly in order to use with charts
SQL records filtered with my query:
One general approach for get the total monsters killed by each user on the latest X days and make a score calculation like the one you propose on the commentaries can be like this:
SET #daysOnHistory = X; -- Where X should be an integer positive number (like 10).
SELECT
nickname,
SUM(bestia1) AS total_bestia1_killed,
SUM(bestia2) AS total_bestia2_killed,
SUM(bestia3) AS total_bestia3_killed,
SUM(bestia4) AS total_bestia4_killed,
SUM(bestia5) AS total_bestia5_killed,
SUM(bestia1 + bestia2 + bestia3 + bestia4 + bestia5) AS total_monsters_killed,
SUM(bestia1 + 2 * bestia2 + 3 * bestia3 + 4 * bestia4 + 5 * bestia5) AS total_score
FROM
reporte
WHERE
fecha >= DATE_ADD(DATE(NOW()), INTERVAL -#daysOnHistory DAY)
GROUP BY
nickname
ORDER BY
total_score DESC
Now, if you want the same calculation but only taking into account the days of the current week (assuming a week starts on Monday), you need to replace the previous WHERE clause by next one:
WHERE
fecha >= DATE_ADD(DATE(NOW()), INTERVAL -WEEKDAY(NOW()) DAY)
Even more, if you want all the same, but only taking into account the days of the current month, you need to replace the WHERE clause by:
WHERE
MONTH(fecha) = MONTH(NOW())
For evaluate the statistics on the days of the current year, you need to replace the WHERE clause by:
WHERE
YEAR(fecha) = YEAR(NOW())
And finally, for evaluation on a specific range of days you can use, for example:
WHERE
DATE(fecha) BETWEEN CAST("2018-10-15" AS DATE) AND CAST('2018-11-10' AS DATE)
I hope this guide will help you and clarify your outlook.
This will give you number of monster killed in the last 30 days per user :
SELECT
nickname,
sum(bestia1) as bestia1,
sum(bestia2) as bestia2,
sum(bestia3) as bestia3,
sum(bestia4) as bestia4,
sum(bestia5) as bestia5
FROM
reporte
WHERE fecha >= DATE_ADD(curdate(), interval -30 day)
GROUP BY nickName
ORDER BY

Query with three tables, no common column

I've just started a job and my boss wants me to learn mySQL so please bear with me, i've been learning for only 2 days and i'm not that good at it yet.
So i've been given 3 tables and several tasks to do.
The tables are:
mobile_log_messages_sms
mobile_providers
service_instances
And in them i've got to:
Find out how many messages there were in the last 25 days and how
much income did they make
Then i need to group them by day (so per day, exclude hours) and
provider name.
Also i need to ignore all the messages that have an empty string
under the service column
Also i need to ignore the messages that made 0 income and count only
those that have the column service_enabled = 1
And then i need to sort it descending, by date.
in the tables
mobile_log_messages_sms:
message_id - used to count the messages
price - using for price obviously, exlude those with 0
time - date in yyyy/mm/dd hh:mm:ss format
service - exclude all those that have an empty string (or null)
mobile_providers
provider_name - to use to group with
service_instances
enabled - only use if value is 1
I've started with:
SELECT message_id, price, time
FROM mobile_log_messages_sms
WHERE time BETWEEN '2017-02-26 00:00:00'
AND time AND '2017-03-22 00:00:00'
But i need to change the date format and then use the JOIN commands but i don't know how, and i know i need to add more to it, but i'm stumped even at the start. Also the starting just lists the messages but i need to count the total sum of the income (price) per day.
Can anyone point me in the right direction at least since i'm still a noob? Many thanks in advance and sorry if i worded something badly, english is not my first language.
Find out how many messages there were in the last 25 days and how much income did they make
1.
SELECT COUNT(message_id), SUM(price)
FROM mobile_log_messages_sms
WHERE CAST(time AS DATE) BETWEEN DATE_SUB(CURRENT_DATE,INTERVAL 25 DAY)
AND CURRENT_DATE;
2.
SELECT COUNT(message_id), SUM(price)
FROM mobile_log_messages_sms
WHERE CAST(time AS DATE) BETWEEN DATE_SUB(CURRENT_DATE,INTERVAL 25 DAY)
AND CURRENT_DATE
GROUP BY CAST(time AS DATE);
3.
SELECT COUNT(message_id), SUM(price)
FROM mobile_log_messages_sms
WHERE CAST(time AS DATE) BETWEEN DATE_SUB(CURRENT_DATE,INTERVAL 25 DAY)
AND CURRENT_DATE AND service IS NULL
GROUP BY CAST(time AS DATE);
rest can't done with join so make sure that at least one column should be common in tables.

SQL query for calculating a monthly total out of a running total

I have a table titled "Reports" in MySQL that has a column titled "Flow_Total" which has a running total value that goes up every day and never resets, what i need is a query that takes the values that are stored in the "Flow_Total" column and divide them by month and tells me how much the value goes up every month.
This is how i would like to see the data:
https://skydrive.live.com/redir?resid=BC22A6E2F92CE833!11843&authkey=!ACgipFLKDJTBlN8
The value for the month is written on the last day of that month.
A summary of what i want to do is subtract the monthly change from the Flow_Total and display it in a separate column titled Monthly Total.
Maybe not the most pleasing SQL to the eyes, but this should do what you're asking; it'll just self join the table with itself delayed 1 month and calculate the difference from that.
SELECT DATE_FORMAT(MAX(a.`DATE`), '%b-%y') `DATE`,
MAX(a.`FLOW_TOTAL`) `Flow Total`,
(MAX(a.`FLOW_TOTAL`) - MAX(b.`FLOW_TOTAL`)) `Monthly Total`
FROM Reports a
LEFT JOIN Reports b
ON YEAR(a.`DATE`) = YEAR(DATE_ADD(b.`DATE`, INTERVAL 1 MONTH)) AND
MONTH(a.`DATE`) = MONTH(DATE_ADD(b.`DATE`, INTERVAL 1 MONTH))
GROUP BY YEAR(a.`DATE`), MONTH(a.`DATE`)
ORDER BY a.`DATE` DESC;
An SQLfiddle for testing.

MySQL group by calculated field

I have members that have to pay for their membership. And I store: payment date, and membership length (they can pay for 1 month or several).
Now I'd like to know which payments are overdue, or soon to be.
My logic was: get an expiration date for each membership (last payment date + membership length) and then just look at the highest value of that for each member.
Here's my query, but I did want to explain my reasoning, as you may want to question that or even the format of the DB (but please don't ask me to store the expiration date).
SELECT tbl.company AS company,
MAX(ADDDATE( paydate, INTERVAL paylength MONTH ))) AS expiration,
tbl.id
FROM tblPayments
JOIN tbl ON tblPayments.comp_id = tbl.id
GROUP BY expiration
ORDER BY expiration ASC
I've read that grouping by calculated fields may not be possible, but my knowledge of MySQL is not strong enough to understand the workarounds. I'd appreciate any help you can provide! Thanks!
You are grouping by the aggregated result of your group which is not possible and not what you intended. Based on your explanation I would think you are trying to do this
SELECT
tbl.company AS company,
MAX(ADDDATE( paydate, INTERVAL paylength MONTH )) AS expiration,
tbl.id
FROM tblPayments
JOIN tbl
ON tblPayments.comp_id = tbl.id
GROUP BY tbl.company , tbl.id
HAVING expiration < NOW()
ORDER BY expiration ASC
And #dleiftah brings up a good point, you cannot always use the alias although MySQL seems to let you in a GROUP BY whereas MSSQL never does. I forget exactly when...