Get top 10 users data based on the number of sales - mysql

I have table 'sales' and data like this scheme:
User | Amount| Month
user a 100 1
user b 240 1
user c 120 1
user a 200 2
user b 130 2
user c 240 2
How to get TOP 5 user based on Total Sales every month, I've tried using query like this, but there's always showed an error
SELECT TOP10 USER,
SUM(amount) amount
FROM sales LIMIT 10
WHERE MONTH BETWEEN 1 AND 12
GROUP BY sales
ORDER BY 2 DESC
And the result should be:
User a | 300
User b | 370
User c | 360
So the order must be: B, C, A

You can do a GROUP BY on User, and use SUM(amount) to get the total_sales per user. Now, simply sort the result-set by total_sales in Descending order, to get the highest sales first.
We can use LIMIT 10, in case you want to get only Top 10.
SELECT User,
SUM(amount) AS total_sales
FROM sales
WHERE MONTH BETWEEN 1 AND 12
GROUP BY User
ORDER BY total_sales DESC
LIMIT 10

You can try below
SELECT USER, SUM(amount) amount
FROM sales
WHERE MONTH BETWEEN 1 AND 12
GROUP BY USER
ORDER BY amount DESC

Related

MySQL Query to get the first user that sums X sales

I'm looking for help with a query.
I have a users table and a sales table. Sales are stored with their date, amount and quantity.
I need to get the first user that reaches an X sum of amount or Y sum of sales.
So I would need to take the sale date in account in order to know which user gets it first.
Can anyone give me a hand with this query or should I use another approach?
I'm currenlty using MySQL 8.0.32.
Here are some sample tables and an example of what is needed.
Users
id
username
1
user1
2
user2
Sales
id
amount
quantity
date
user_id
1
1000
2
2023-01-05
1
2
1500
3
2023-01-05
2
3
500
1
2023-01-07
1
4
1500
3
2023-01-10
1
5
500
1
2023-01-12
1
6
2500
5
2023-01-12
2
7
1000
2
2023-01-15
1
In this case, lets assume that the goal is the first user to sum >=4000. So user2 would be the winner as it reaches to 4000 before user1 even when at the end user1 sums 4500.
I would expect to get the lists of users untill the date that the first user get to the goal ie:
user_id
sum_amount
date
2
4000
2023-01-12
1
3500
2023-01-12
That would be super, but I could handle getting the first user got to the goal.
Thanks.
For MySql 8.0+ you can use SUM() window function to calculate the running total an sort the rows first by the rows that are equal or greater than 4000 and then the date:
SELECT user_id
FROM sales
ORDER BY SUM(amount) OVER(PARTITION BY user_id ORDER BY date) >= 4000 DESC,
date
LIMIT 1;
For previous versions of MySql use a correlated subquery that emulates the functionality of SUM() window function:
SELECT s1.user_id
FROM sales s1
ORDER BY (SELECT SUM(s2.amount)
FROM sales s2
WHERE s2.user_id = s1.user_id AND s2.date <= s1.date
) >= 4000 DESC,
s1.date
LIMIT 1;
See the demo.

Get original RANK() value based on row create date

Using MariaDB and trying to see if I can get pull original rankings for each row of a table based on the create date.
For example, imagine a scores table that has different scores for different users and categories (lower score is better in this case)
id
leaderboardId
userId
score
submittedAt ↓
rankAtSubmit
9
15
555
50.5
2022-01-20 01:00:00
2
8
15
999
58.0
2022-01-19 01:00:00
3
7
15
999
59.1
2022-01-15 01:00:00
3
6
15
123
49.0
2022-01-12 01:00:00
1
5
15
222
51.0
2022-01-10 01:00:00
1
4
14
222
87.0
2022-01-09 01:00:00
1
5
15
555
51.0
2022-01-04 01:00:00
1
The "rankAtSubmit" column is what I'm trying to generate here if possible.
I want to take the best/smallest score of each user+leaderboard and determine what the rank of that score was when it was submitted.
My attempt at this failed because in MySQL you cannot reference outer level columns more than 1 level deep in a subquery resulting in an error trying to reference t.submittedAt in the following query:
SELECT *, (
SELECT ranking FROM (
SELECT id, RANK() OVER (PARTITION BY leaderboardId ORDER BY score ASC) ranking
FROM scores x
WHERE x.submittedAt <= t.submittedAt
GROUP BY userId, leaderboardId
) ranks
WHERE ranks.id = t.id
) rankAtSubmit
FROM scores t
Instead of using RANK(), I was able to accomplish this by with a single subquery that counts the number of users that have a score that is lower than and submitted before the given score.
SELECT id, userId, score, leaderboardId, submittedAt,
(
SELECT COUNT(DISTINCT userId) + 1
FROM scores t2
WHERE t2.userId = t.userId AND
t2.leaderboardId = t.leaderboardId AND
t2.score < t.score AND
t2.submittedAt <= t.submittedAt
) AS rankAtSubmit
FROM scores t
What I understand from your question is you want to know the minimum and maximum rank of each user.
Here is the code
SELECT userId, leaderboardId, score, min(rankAtSubmit),max(rankAtSubmit)
FROM scores
group BY userId,
leaderboardId,
scorescode here

LIMIT and Group By? How do I return the lowest 100 earning customers by country? SQL

Hi I’ve a table database1
3 columns : customer_id , income , country
Customer_id
1001
1002
...
Income
5000
6000
7000
Country
SG
HK
VN
...
How do I write a query that returns the lowest 100 earning customers per country?
Is it possible to return:
Customer ID | country code
1003 SG
1004 SG
...
1007 VN
...
So on
Thanks!
On mySQL 8 you can leverage a window function for this:
SELECT * FROM
(
SELECT
country,
customer_id,
row_number() over(partition by country order by income asc) earn_rank
FROM table
)x
WHERE x.earn_rank <= 100
You can conceive that this window function will sort the rows by country then by income, then start counting up from 1. Each time the country changes the row numbering starts over from 1 again. This means that for every country there will be a row numbered 1 (with the lowest income), and a 2, 3 etc. If we then wrap it up in another outer query that selects only rows where the number is less than 101 we get 100 rows per country

how to select row with max value, while excluding the newest added row

I have a table with user ids and the total spend for every order the user has placed. I need to find the highest total spend for every order excluding their latest order.
I'm not sure how to drop their last order without purchase dates- the table is in ascending order so the last row would be the latest purchase.
user_id total_spend
1 234
2 123
3 56
1 453
5 560
1 232
2 345
3 210
ideal output
user_id total_spend
1 453
2 123
3 56
select user_id, max(total_spend)
from t
group by user_id
does anyone have any ideas of how to solve this?
Assuming you have an extra column such as id of integer type,which determines the row adding order, and starting from upside with 1 and incrementing by 1 upto 8th row in your illustration, then you can use this query :
select t1.user_id, max(t1.total_spend)
from tab t1
join
(
select max(id) as id, user_id
from tab
group by user_id ) t2
on t1.id < t2.id
and t1.user_id = t2.user_id
group by t1.user_id;
which filters out the latest id columns first, and then gets maximum total spend money grouped by the rest of user ids.
Demo

Select User Having Maximum Rating

I have a table which stores the rating given by the user.
eg:
UserId Rating
3 1
3 2
1 1
1 2
1 3
1 4
2 1
2 23
2 4
I need to retrieve the 10 users who have rated the maximum number of times.
eg:
1 rated 4 times
2 rated 3 times
3 rated 2 times...
Any idea how to write a query using mysql?
You have to group by userID, count the grouped rows, and order by the count in descending order, then you limit the query to 10 rows:
SELECT userID, count(*) times
FROM users
GROUP BY userID
ORDER BY times DESC
LIMIT 10
If you need the output exactly as shown above, try this:
SELECT CONCAT_WS(' ', userID, 'rated', count(*), 'times')
FROM users
GROUP BY userID
ORDER BY count(*) DESC
LIMIT 10
See this fiddle.