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
Related
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
I have a table with id, city_id, and stock which looks like this.
id
city_id
stock
1
1
1000
2
2
500
3
3
11000
4
2
600
5
3
12000
6
1
2000
9
3
13000
10
1
3000
11
1
4000
12
2
700
To select the latest stock values for each city_id I used the following query, which works fine.
SELECT `stock`
FROM `stock_table`
WHERE id in ( SELECT MAX(id)
FROM `stock_table`
GROUP BY city_id
);
It returns
stock
13000
4000
700
Now I want to select 2nd latest stock entry for each city_id. So the output should be like the following table.
stock
12000
3000
600
Any help is greatly appreciated. Thanks!
In MySQL 8 you can use the row_number() window function to assign a number to each row ordered by the id per partition of city_id. Then just filter on that being 2 (in your example; you can use any number).
SELECT x.stock
FROM (SELECT s.stock,
row_number() OVER (PARTITION BY s.city_id
ORDER BY s.id DESC) rn
FROM stock_table s) x
WHERE x.rn = 2;
u can use group by with row number and get rownumber 2
ROW_NUMBER() OVER (PARTITION BY city_id ORDER By id) as ROW
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
Need MySQL query for below problem
Consider a table having student and their marks in a particular subject
Schema
std_id int(11)
marks int(11)
Sample data
std_id marks
1 10
2 15
3 90
4 120
5 25
6 29
7 121
8 122
Now I have an web app in which a form will take a input (int) from user.
For eg 12
then I am required to show total number of student ids (std_id) and their corresponding marks group.
Eg
std_total (tot no of students) group (marks range we got from form)
1 0-11
1 12-23
2 24-35
1 84-95
3 120-131
#Barmar Your answer was almost correct, I made few changes to clean the output. Your query gives output as below :
0-11 2
1-12 2
2-13 1
3-14 1
4-15 1
6-17 1
7-18 2
My query return Outout as
0-11 2
12-23 2
24-35 1
36-47 1
48-59 1
72-83 1
84-95 2
SELECT CONCAT(FLOOR(marks/12)*12, '-', FLOOR(marks/12)+11*(FLOOR(marks/12))+11) AS `group`, COUNT(*) as `std_total`
FROM yourTable
GROUP BY `group`
Use division and FLOOR() to get the beginning of each range.
SELECT CONCAT(FLOOR(marks/12), '-', FLOOR(marks/12)+11) AS `group`, COUNT(*) as `std_total`
FROM yourTable
GROUP BY `group`
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