How can I get the sum of a row using LIMIT - mysql

id
reg_No
Subj_id
sub_title
score
Class_id
1
98
23
MATHEMATICS
90
2
2
98
21
ENGLISH LANG
60
2
3
98
24
PHYSICS
78
2
4
98
23
CHEMISTRY
100
2
5
98
21
BIOLOGY
81
2
6
98
24
AGRICULTURE
87
2
I want to select the best SUM(score) of the four(4) subjects including English and mathematics.
It suppose to sum 90+60+100+87 = 337
But, it's summing the entire column
Here is my query
SELECT SUM(score)
FROM table1
WHERE reg_no = 98
AND class_id=2
ORDER BY CASE WHEN sub_title IN ('English Language','Mathematics')
THEN 0
ELSE 1 END, score DESC LIMIT 4

The priority of SELECT is higher than LIMIT, therefore, you have to use a subquery
SELECT sum(score)
FROM
(
SELECT *
FROM tab
WHERE reg_no = 98 AND class_id=2
ORDER BY CASE WHEN sub_title IN ('English Language','Mathematics')
THEN 0
ELSE 1 END, score DESC
LIMIT 4
) t
DEMO

An easy way to split into two queries. The first one gets the Math and English score values, and the second one gets the two highest scores from the remaining values.
SQL Server:
With CTE As (
Select Top 2 Score From table1 Where reg_no = 98 And class_id=2 And sub_title Not In ('MATHEMATICS','ENGLISH LANG')
Order by Score Desc
Union All
Select Score From table1 Where reg_no = 98 And class_id=2 And sub_title In ('MATHEMATICS','ENGLISH LANG')
)
Select Sum(Score)
From CTE
MySQL:
With CTE As (
Select Score
From
(Select Score From table1 Where reg_no = 98 And class_id=2 And sub_title Not In ('MATHEMATICS','ENGLISH LANG')
Order by Score Desc
Limit 2) As S
Union All
Select Score From table1 Where reg_no = 98 And class_id=2 And sub_title In ('MATHEMATICS','ENGLISH LANG')
)
Select Sum(Score)
From CTE

Related

Select multiple tables with only unique users and ordered by latest id

I have 2 tables, first one is called members:
id name show
1 John 1
2 Wil 1
3 George 1
4 Chris 1
Second is called score:
id user_id score
1 1 90
2 1 70
3 2 55
4 3 30
5 3 40
6 3 100
7 4 30
user_id from score is the id of members.
What I want is to show a scorelist with unique members.id, ordered by score.score and order by the latest score.id.
I use the following code:
SELECT members.id, members.show, score.id, score.user_id, score.score FROM members
INNER JOIN score ON score.user_id = members.id
WHERE members.show = '1'
GROUP BY score.user_id
ORDER BY score.score DESC, score.id DESC
The output is not ordered by the latest score.id, but it does show only unique user_id's:
id user_id score
1 1 90
3 2 55
4 3 30
7 4 30
It should be like:
id user_id score
6 3 100
2 1 70
3 2 55
7 4 30
I hope you can help me
You could use:
with cte as (
select id,
user_id,
score,
row_number() over(partition by user_id order by id desc) as row_num
from score
) select cte.id,user_id,score
from cte
inner join members m on cte.user_id=m.id
where row_num=1
order by score desc;
Demo
If your MySQL server doesn't support windows function, use:
select s.id,s.user_id,s.score
from score s
inner join members m on s.user_id=m.id
where s.id in (select max(id) as id
from score
group by user_id
)
order by score desc;
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

PHP SQL order by multiple rows

I have a table called 'scorelist' with the following results:
ID USER_ID SCORE SEASON
-----------------------------
1 1 35 3
2 1 45 2
3 2 80 3
4 2 85 1
5 3 65 2
I want to make a score list where I show the scores of the users but only of their last played season.
Result should be:
ID USER_ID SCORE SEASON
-----------------------------
3 2 80 3
5 3 65 2
1 1 35 2
I use the following code:
SELECT * FROM scorelist
WHERE season = (
SELECT season FROM scorelist ORDER BY season DESC LIMIT 1
)
GROUP BY user_id
ORDER BY score DESC;
But then I only get the results of season 3, so a lot of users are not shown.
I also tried:
SELECT * FROM scorelist group by user_id ORDER BY score DESC, season DESC
But this is also not working.
I hope you can help me.
The subquery gets the latest season for each user. If you join to that you get your desired results
SELECT s1.*
FROM scorelist s1
JOIN
(
SELECT user_id, max(season) AS season
FROM scorelist
GROUP BY user_id
) s2 ON s1.user_id = s2.user_id AND s1.season = s2.season
Since MySQL 8.0 you can use window function row_number to solve this problem:
WITH ordered_scorelist AS (
SELECT
scorelist.*,
row_number() over (partition by USER_ID order by SEASON DESC) rn
FROM scorelist
) SELECT
USER_ID, SCORE, SEASON
FROM ordered_scorelist
WHERE rn = 1
ORDER BY SCORE DESC;
MySQL row_number test

MySQL group by with max value

Hi I have this table.
id lat lng userId
1 12 23 1
2 45 34 2
3 42 34 3
4 33 34 1
5 36 79 2
6 53 98 2
7 23 90 3
8 23 67 1
Here we have three users. (user ids 1,2,3). I want to get lateset record (id column max value) of each user.
My excepted output is this
userId lat lng
1 23 67
2 53 98
3 23 90
This query will give me group by option
SELECT
*
FROM
covid.locations
GROUP BY userId;
But how do I combine this with MAX(id) function.
One way is to use the following:
SELECT
cl.*
FROM covid.locations cl
INNER JOIN (
SELECT
userid
, MAX( id ) mid
FROM covid.locations
GROUP BY
userId
) g ON cl.userid = g.userid
AND cl.id = cl.mid
Another is to use row_number() over()
SELECT
userId
, lat
, lng
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY id DESC) rn
FROM covid.locations
GROUP BY
userId
) d
WHERE rn = 1
Both will identify the "most recent" row in the source table based in the id column of that table. Note that the second query requires MySQL version 8+ as this is when row_number() became supported in that database. The first query should run in dbms supporting SQL.
This will do
SELECT
*
FROM
covid.locations
where id in (select max(t.id) from covid.locations t group by t.userId)
order by id desc;
An example of the above query can be found in this SQLFiddle

How to get count greater than and less than average values group by name

I have a data set with name and their transaction ,how to get average and count of transactions grater than that average and less than that average..
Name Transaction
John 12
John 34
John 45
John 66
John 32
chris 26
chris 54
chris 56
chris 99
chris 13
chris 4
kim 22
kim 34
kim 7
kim 11
kim 34
O/P will be
Name Avg Count_greater_than_Avg Count_Less_than_Avg
John 37.8 2 3
chris 42 3 3
kim 21.6 3 2
Thanks in advance..
Try this:
SELECT t1.Name, t2.Aver,
COUNT(CASE WHEN Transaction < Aver THEN 1 END) Count_Less_than_Avg,
COUNT(CASE WHEN Transaction > Aver THEN 1 END) Count_greater_than_Avg
FROM mytable AS t1
JOIN (
SELECT Name, AVG(Transaction * 1.0) AS Aver
FROM mytable
GROUP BY Name
) AS t2 ON t1.Name = t2.Name
GROUP By Name
You need a derived table in order to calculate the average value per Name. You can then JOIN the original table to this derived table and use conditional aggregation in order to calculate less than, greater than number of transactions.
Demo here
This basically first add a column Your_Avg using a correlated query, and then wrap it with another select to select the count of the occurrences of times smaller then avg and times larger.
SELECT tt.name,tt.Your_Avg,
count(CASE WHEN tt.Your_Avg > tt.Transaction then 1 end) as Greater_Then_Avg,
count(CASE WHEN tt.Your_Avg > tt.Transaction then 1 end) as Smaller_Then_Avg
FROM(
SELECT t.name,
(SELECT avg(s.transaction) FROM YourTable s WHERE s.name = t.name) as Your_Avg,
t.transaction
FROM YourTable) tt
GROUP BY tt.name