SQL, get the highest payment month of each year - mysql

I currently have this that shows me the total of how much the amount is per month. What i want to get from this, is to show the month that made the highest amount per each year.
SELECT year(paymentDate), month(paymentDate) , SUM(amount)
FROM classicmodels.payments
GROUP BY year(paymentDate), month(paymentDate)
ORDER BY paymentDate ASC;
Here is the table that i want to only show the month that got the highest amount for each year

You can use ROW_NUMBER for this:
SELECT y, m, amount
FROM (
SELECT YEAR(paymentDate) AS y, MONTH(paymentDate) AS m,
amount,
ROW_NUMBER() OVER (PARTITION BY YEAR(paymentDate) ORDER BY amount DESC) AS rn
FROM classicmodels.payments) AS t
WHERE t.rn = 1
Note: In case of ties the query return an arbitrary month. To return all months having the biggest amount use RANK instead of ROW_NUMBER.

Using ROW_NUMBER() you can assign sequence number for each records based on your criteria, and select the record with sequence 1.
Sample below;
SELECT *
FROM (
SELECT year(paymentDate) year_val, month(paymentDate) month_val, SUM(amount) amt_val,
ROW_NUMBER() OVER(PARTITION BY year(paymentDate) ORDER BY SUM(amount) DESC) AS ROW_ORDER
FROM classicmodels.payments
GROUP BY year(paymentDate), month(paymentDate)
) AS D
WHERE D.ROW_ORDER = 1
There are lot of other ways to achieve the same.
and WHERE D.ROW_ORDER = n --you will return the n'th highest for each year.

Give SUM(Amount) a column alias, ORDER BY <that alias> DESC and add TOP(1) to the SELECT

Related

How can i get substaction calculation row between multiple dates and display the percentage?

I have the following information using group by and some calculations
I'm trying to calculate the maximum difference value between several dates in this example are 3 dates (2022, 2021, 2020), the oldest date should calculate 0 because won't do substractions.
After detecting the maximun difference between the previous year, it must calculate the percentage:
After doing the query for maximum difference calculation between date rows. The final result should be this:
Demo with 4 dates: https://dbfiddle.uk/KF-d2KpR?hide=4
The following query is displaying without percentage:
WITH cte1 AS (
SELECT
a.date_rehearsal,
a.col1_val,
ROW_NUMBER() OVER (PARTITION BY a.date_rehearsal ORDER BY a.date_rehearsal DESC) AS rn
FROM demo a
),
cte2 AS (
SELECT
b.date_rehearsal,
b.col1_val - COALESCE(LEAD(b.col1_val) OVER (PARTITION BY b.rn
ORDER BY b.date_rehearsal DESC), b.col1_val) AS diff
FROM cte1 b)
SELECT
c.date_rehearsal AS 'Dates',
MAX(c.diff) as 'max_col1_val_difference'
FROM cte2 c
GROUP BY c.date_rehearsal
ORDER BY c.date_rehearsal DESC
Can you please help me this operation to display with percentage?
Thanks in advance.
You can use a CTE to get the ROW_NUMBER by date, then SELECT the MAX difference, GROUPED BY date, using a subquery that will take the current col1_val and subtracting it from the subsequent row's value using LEAD partitioned by the ROW_NUMBER from the CTE. If the subsequent row is NULL, then subtract it from the current row's col1_val using COALESCE, which will return zero for the earliest year in your table (in your case, 2020).
WITH cte AS (
SELECT
a.date_rehearsal,
a.col1_val,
ROW_NUMBER() OVER (PARTITION BY a.date_rehearsal ORDER BY a.date_rehearsal DESC) AS rn
FROM demo a
)
SELECT
c.date_rehearsal AS 'Dates',
MAX(c.diff) as 'max_col1_val_difference',
ROUND(MAX(c.diffPercent),2) as 'max_col1_val_percent',
CONCAT(MAX(c.diff), ' (', ROUND(MAX(c.diffPercent),2), '%)') as 'max_dif_with_percentage'
FROM (
SELECT
b.date_rehearsal,
b.col1_val - COALESCE(LEAD(b.col1_val) OVER (PARTITION BY b.rn ORDER BY b.date_rehearsal DESC), b.col1_val) AS diff,
(((b.col1_val - COALESCE(LEAD(b.col1_val) OVER (PARTITION BY b.rn ORDER BY b.date_rehearsal DESC), b.col1_val))/b.col1_val)*100) AS diffPercent
FROM cte b) c
GROUP BY c.date_rehearsal
ORDER BY c.date_rehearsal DESC
Result:
Dates
max_col1_val_difference
max_col1_val_percent
max_dif_with_percentage
2022-07-01
6
5.08
6 (5.08%)
2021-07-01
10
10.00
10 (10.00%)
2020-07-01
0
0.00
0 (0.00%)
db<>fiddle here.

Average timediff of 2nd and 3rd datetimes for a group

I need to find the average time in days between a customer's second order and third order
I know that I need to use the timestampdiff but am quite at a loss for how to select the second and third dates and need some sort of nest.
SELECT CustomerID,
OrderDate,
diff,
avg(timestampdiff(day, start_date, end_date)) AS average_days
FROM () o3
WHERE date3, date2
ORDER BY CustomerID, OrderDate;
Table
To achieve your desired result, you first need to calculate ROW_NUMBER from your data PARTITION BY CustmerId. Then keep rows only with RowNumber IN (2,3) and then get the DateDiff between two days. The following query will help getting your desired results-
SELECT CustomerID,datediff(MAX(OrderDate),MIN(OrderDate))
FROM
(
SELECT *,
#row_num :=IF(#prev_value = concat_ws('',CsutomerID),#row_num+1,1)AS RowNumber
, #prev_value := concat_ws('',CsutomerID)
FROM your_table A
ORDER BY CustomerID,OrderDate
)B
WHERE B.RowNumber IN (2,3)
GROUP BY CustomerID;

Mysql query - GROUP BY and show the highest COUNT(*)

I'm doing a small project and I'm trying to get the restaurant with the most votes each week to be displayed once.
This is my query:
SELECT votedRestaurant,
week,
COUNT(*)
FROM mylunch.votes
GROUP BY votedRestaurant,
week
ORDER BY week DESC;
This gets me the following result:
I would only like to have the one with the highest COUNT(*) displayed per week.
Thanks for any help.
you can try use LIMIT and ordering by count, for example
SELECT votedRestaurant,
week,
COUNT(*) AS tcount
FROM mylunch.votes
GROUP BY votedRestaurant,
week
ORDER BY tcount DESC
LIMIT 1;
Also, you can use subquery, so says the documentation.
Using Mysql 8 you can make use of window functions
WITH
cte AS (SELECT votedRestaurant, WEEK, COUNT(*) total
FROM votes
GROUP BY votedRestaurant,WEEK
ORDER BY WEEK DESC, votedRestaurant)
SELECT *
FROM (
SELECT *,
row_number() over (PARTITION BY WEEK ORDER BY total DESC) AS rn
FROM
cte
) t
WHERE rn = 1
Demo
Another way would be by using string fuctions
SELECT t.week, SUBSTRING_INDEX(GROUP_CONCAT(t.votedRestaurant ORDER BY t.total DESC),',',1) votedRestaurant, MAX(t.total)
FROM(
SELECT votedRestaurant, WEEK, COUNT(*) total
FROM votes
GROUP BY votedRestaurant,WEEK
ORDER BY WEEK DESC
) t
GROUP BY t.week
ORDER BY t.week DESC
Demo

MySQL - max summary by month

I have this entity:
payments(idPayment, idGroup, price, paymentDate)
and I would like to find out max month (recordable month). I have max price, but month is wrong.
Select Max(x.price), x.month, x.year from(
SELECT SUM(price) as price, Year(paymensDate) as year, Month(paymentDate) as month FROM `payments`
where idGroup=27 group by Year(paymentDate), Month(paymentDate)
) as x
Thanks for advices
You could use ORDER BY and LIMIT to pick the row with highest price amount
SELECT SUM(price) as price,
YEAR(paymensDate) as year,
MONTH(paymentDate) as month
FROM `payments`
WHERE idGroup=27
GROUP BY YEAR(paymentDate),
MONTH(paymentDate)
ORDER BY price DESC
LIMIT 1
MAX will give the max value for provided column but other values of column are not guaranteed to return the same values from that row which is picked by max

MySQL Finding the MAX of the SUM of each month of the year [MYSQL]

Currently i am able to get the sum for the highest amount for each month of the year. But what i want to do, is to be able to get the SUM of the month that has the highest value in amount for each year.
SELECT year(paymentDate), month(paymentDate) , SUM(amount)
FROM classicmodels.payments
GROUP BY year(paymentDate), month(paymentDate)
ORDER BY SUM(amount) DESC;
This orders the highest SUM(amount) in descending order but i only want to get the highest month for each year. there are only 3 years in my database.
Here's what happening on mysql workbench
One method uses a having clause:
SELECT year(p.paymentDate), month(p.paymentDate), SUM(p.amount)
FROM classicmodels.payments p
GROUP BY year(p.paymentDate), month(p.paymentDate)
HAVING SUM(p.amount) = (SELECT SUM(p2.amount)
FROM classicmodels.payments p2
WHERE year(p2.paymentDate) = year(p.paymentDate)
GROUP BY month(p2.paymentDate)
ORDER BY SUM(p2.amount) DESC
LIMIT 1
)
ORDER BY SUM(amount) DESC;