How to use ROW_NUMBER() function mysql after the ORDER BY? - mysql

SELECT user.id
,user.emp_id
,user.name,COUNT(transfer.record_name) AS current_rank
,ROW_NUMBER() OVER () AS count
FROM transfer AS transfer
LEFT JOIN users AS user ON user.emp_id= transfer.user_id
WHERE transfer.lobs= 0
AND transfer.shift_date = '2020-03-27'
GROUP BY user.emp_id
ORDER BY current_rank DESC
This query will give me a result of like this:
user.id| user.emp_id| user.name| current_rank| count
25 1234 test1 4 4
30 4321 test2 2 2
18 5678 test3 1 1
12 8765 test4 1 3
My goal is to use ORDER BY DESC first so that I can order the current_rank and the count column should have the count of:
user.id| user.emp_id| user.name| current_rank| count
25 1234 test1 4 1
30 4321 test2 2 2
18 5678 test3 1 3
12 8765 test4 1 4
How can I use the ROW_NUMBER() function after I ORDER BY my current_rank column?
Thank you any help. I will appreciate it.

The result of ROW_NUMBER() is not affected by the sort in the query.
Instead, it accepts an ORDER BY option within its OVER clause: without it, the ordering of ROW_NUMBER() is undefined, meaning that the database is free to order the rows as it likes. You may observe that the same ordering is used over consecutive executions, but the database does not guarantee it.
So, do add an ORDER BY to the window function:
ROW_NUMBER() OVER (ORDER BY COUNT(transfer.record_name) DESC) AS count

Related

Group By with Max Date and another column

I have the following table.
id
user_id
file_id
completed
updated
1
161
10
1
2022-10-11
2
164
11
1
2022-10-12
3
161
10
1
2022-10-12
4
167
10
1
2022-10-10
5
167
10
1
2022-10-11
6
167
10
1
2022-10-12
I want to select the row for each user having the max updated date for each file_id.
SELECT * FROM user_file
WHERE updated = (SELECT uf.updated FROM user_file uf GROUP BY uf.user_id,uf.file_id)
I have come up with this query but it returns an error "Subquery returns more than 1 row"
Maybe you want to check these out?
SQL select only rows with max value on a column
Retrieving the last record in each group - MySQL
Personally prefer the window function solution
SELECT a.*
FROM (SELECT id, user_id, file_id, ...
ROW_NUMBER() OVER (PARTITION BY file_id ORDER BY updated DESC) ranked_order
FROM user_file) a
WHERE a.ranked_order = 1

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

Sum values in mysql table where userid is identical

I have read the different answers here on SO, but I am stuck on this question. Please help.
I have this mysql view named "activeuser":
userid COUNT(*) ACRONYM
1 23 admin
2 2 doe
3 4 tompa
12 4 Marre
13 1 Mia
1 2 admin
3 1 tompa
12 1 Marre
13 1 Mia
2 1 doe
3 1 tompa
12 1 Marre
How can I sum the COUNT column so that I get the following wanted result?
userid COUNT(*) ACRONYM
1 25 admin
2 3 doe
3 6 tompa
12 6 Marre
13 1 Mia
EDITED:
I used this query to create the view:
CREATE VIEW activeuser AS
(SELECT boats_comments.userid, COUNT(boats_comments.userid), boats_user.acronym, boats_user.email
FROM boats_comments
INNER JOIN boats_user
ON boats_comments.userid = boats_user.id
GROUP BY boats_comments.userid
ORDER BY COUNT(boats_comments.userid) DESC)
UNION ALL
(SELECT boats_answers.userid, COUNT(boats_answers.userid), boats_user.acronym, boats_user.email
FROM boats_answers
INNER JOIN boats_user
ON boats_answers.userid = boats_user.id
GROUP BY boats_answers.userid
ORDER BY COUNT(boats_answers.userid) DESC)
UNION ALL
(SELECT boats_questions.userid, COUNT(boats_questions.userid), boats_user.acronym, boats_user.email
FROM boats_questions
INNER JOIN boats_user
ON boats_questions.userid = boats_user.id
GROUP BY boats_questions.userid
ORDER BY COUNT(boats_questions.userid) DESC)
My goal is to see which users are the most active by checking the number of comments, questions and answers... but I got stuck...
As the results in your view has duplicates I guess the underlying code for the view is grouping on something it maybe shouldn't be grouping on.
You can get the results you want by applying SUM to it:
select userid, sum("whatever column2 is named") as "Count", Acronym
from activeuser group by userid, Acronym;
select userid, count(*) from activeuser group by userid;

MySQL Query for Average Grade of last 2 attempts

I have a table:
quiz userid attempt grade
1 3 1 33
1 3 2 67
1 3 3 90
1 3 4 20
Now, I want the last two attempts i.e., 4 and 3 and I want average grade of these 2 grades i.e, 90 and 20
Could anyone help me?
Use ORDER and LIMIT to get the 2 last attempts and the AVG aggregation function :
SELECT AVG(grade) AS average FROM (
SELECT grade FROM table
WHERE userid = 3
ORDER BY attempt DESC LIMIT 2) AS t
If you want to list both test results separately, with the average in each row, then something like this maybe (otherwise you just need the subquery for the average of the two tests):
SELECT userid, attempt, grade,
( SELECT AVG(grade)
FROM table
ORDER BY attempt DESC LIMIT 0, 2 ) AS avg_grade
FROM table
ORDER BY attempt DESC LIMIT 0, 2;

How can I select the latest of three value types in a MySQL database?

Here is an example table:
ID time data type
0 0100 xyz 0
1 0200 xyz 1
2 0300 xyz 1
3 0400 xyz 2
4 0200 xyz 0
5 0500 xyz 2
6 0300 xyz 0
Data is added based on timestamp so that the last of each type has the latest time stamp.
I would like the result of a SELECT to be:
ID time data type
5 0500 xyz 2
2 0300 xyz 1
6 0300 xyz 0
And so the last of each 'type' is returned.
I can accomplish the above using three SELECT statements as follows:
SELECT time, data, type FROM table WHERE type=0 ORDER BY time DESC LIMIT 1
SELECT time, data, type FROM table WHERE type=1 ORDER BY time DESC LIMIT 1
SELECT time, data, type FROM table WHERE type=2 ORDER BY time DESC LIMIT 1
Is there a way to combine the above three SELECT statements into one?
Any help appreciated.
Chris
select m.ID, m.time, m.data, m.type
from (
select type, max(time) as MaxTime
from MyTable
group by type
) mm
inner join MyTable on mm.type = m.type
and mm.MaxTime = m.time