How to select by two unique field values in mysql - mysql

I have a exam results table which contains examid, level and the point got by the user. As you can see in the table
id examid level points
228 2 1 90
229 3 1 85
230 3 1 65 *
227 1 1 60 *
231 2 2 20
232 1 1 80
For each unique exam the highest points will be selected.
I want to select the rows with highest points for each unique exam and unique level. The row 232 has greater point than the row 227 and 232 will be in my resultset. Another one is the row 229 which has greater point than 230.
After selecting my resultset should be like the following:
id examid level points
228 2 1 90
229 3 1 85
231 2 2 20
232 1 1 80
I tried to query like
SELECT * FROM results WHERE userid = 20 GROUP BY examid ORDER BY points
which results only
id examid level points
227 1 1 60
229 3 1 85
228 2 1 90

SELECT examid, level, MAX(`points`)
FROM score
GROUP BY examid, level
ORDER BY id
See SQLFiddle here

If you want all fields (including id), you can JOIN the table back in.
SELECT results.*
FROM results
JOIN (
SELECT examid, level, max(points) AS points
FROM results
GROUP BY examid, level ) maxPoints
ON results.examid = maxPoints.examid
AND results.level = maxPoints.level
AND results.points = maxPoints.points

If you don't need the id, you can use a simple GROUP BY.
SELECT examid, level, MAX(points) AS points
FROM tablename
GROUP BY examid, level

Related

How to find the smallest value in a row

i need help to create a sql query that can find the smallest value in 1 row , and display it in the last column, like this table.
id
out
mid
in
Smallest
1
200
100
50
50
2
100
150
50
50
3
200
100
250
100
4
50
100
150
50
5
50
100
100
50
6
20
200
100
20
7
-
-
100
100
8
150
-
100
100
this is my query :
On MySQL you may use the scalar LEAST() function:
SELECT id, `out`, mid, `in`, LEAST(`out`, mid, `in`) AS Smallest
FROM yourTable;
If your database doesn't have a LEAST function, we can use a CASE expression as an alternative:
SELECT id, `out`, mid, `in`,
CASE WHEN `out` < mid AND `out` < `in` THEN `out`
WHEN mid < `in` THEN mid
ELSE `in` END AS Smallest
FROM yourTable;
Side note: Both IN and OUT are reserved MySQL keywords, and you should avoid naming your columns with them.

Joining tables while using group by in SQL

I have two tables to join in SQL using the ID column in both. Table 1 has only unique values of ID as follows and I want to keep all columns of this table:
ID code 1 code 2
1 123 99
2 222 09
3 344 13
Table 2 has multiple rows of each ID as follows:
ID application_time Application Number
1 11jan2004 123
2 15oct2010 124
1 24nov2008 845
3 05sep2010 166
1 07feb2001 865
2 24aug2017 545
3 12mar2009 233
2 11dec2001 811
So, from table 2, I want to add the total count of each ID, and Min and Max of Application_time to table 1. I also need to count the number Application Numbers that start with 8. of I do not know where I should use group by (). So the outcome should look like:
ID code 1 code 2 count Min (application_time) Max (application_time)
1 123 99 3 07feb2001 24nov2008
2 222 09 3 11dec2001 24aug2017
3 344 13 2 12mar2009 05sep2010
Count of Application Number starting with 8
2
1
0
here is how you can do it:
select
t1.Id
,t1.code1
,t1.code2
, count(*) count
,min(application_time)
,max(application_time)
, sum( case when left( t2.application number, 1 ) = '8' then 1 else 0 end )
from table1 t1
join table2 t2
on t1.Id = t2.Id
group by
t1.Id
,t1.code1
,t1.code2

SQL sum of maxes of each occurrence

I have the following table:
category id date views
1 3 5-1-17 40
1 3 5-2-17 70
1 3 5-3-17 110
1 3 5-4-17 200
1 5 5-1-17 50
1 5 5-2-17 75
2 6 4-1-17 90
2 6 4-2-17 95
2 9 4-3-17 115
2 9 6-5-17 125
2 9 6-6-17 135
How do I sum the max views for each id by category?
The resulting pull should look like this:
category views
1 275
2 230
For category 1, the max views for id 3 is 200 and the max views for id 5 is 75. The sum for category 1 is thus 275.
For category 2, the max views for id 6 is 95 and the max views for id 9 is 135. The sum for category 2 is thus 230.
You can use two levels of aggregation:
select category, sum(max_views)
from (select category, id, max(views) as max_views
from t
group by category, id
) t
group by category;
You can also use row_number() here:
select category, sum(max_views)
from (select t.*,
row_number() over (partition by category, id, order by views desc) as seqnum
from t
) t
where seqnum = 1
group by category;
It would be interesting which is faster. I would vote on the double aggregation, but that might not always be true.

How to get repeated value in group

I want to find number of repeated value in group using single select query.
I can't use the column in group by for which I want to find number of occurrence in some group.
e.g.
obsid Name Value
1 Ronak 120
2 Ronak 125
3 Ronak 120
4 Pankti 130
5 Pankti 130
6 Sanket 140
7 Aakash 140
8 Unnat 120
Now I want to develop select query in mysql that give me below result
obsid Name Value Value_occurrence
1 Ronak 120 2
2 Ronak 125 1
4 Pankti 130 2
6 Sanket 140 1
7 Aakash 140 1
8 Unnat 120 1
SELECT min(obsid) AS obsid, Name, Value, COUNT(*) AS Value_occurence
FROM yourTable
GROUP BY Name, Value
Group by the desired columns and use COUNT to count the rows in each group:
SELECT MIN(`obsid`) AS `obsid`, `Name`, `Value`, COUNT(*) AS Value_occurrence
FROM yourtable
GROUP BY `Name`, `Value`
Try this online demo which shows your example data and the results for the above query.

MSSQL Select Top 10 winning scores, including Ties and at least one from each category

I got some help finding the top 10 scores, including tied entries, using the following statement
select T.EntryID, T.CategoryID, T.Score
from (
select EntryID, CategoryID, Score,
dense_rank() over(order by Score) as rn
from YourTable
) T
where T.rn <= 10
(thanks [mikael-eriksson]: https://stackoverflow.com/users/569436/mikael-eriksson)
[question]: MSSQL Selecting top 10 but include columns with duplicate values Here is sample data:
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3047 1 80
3048 1 80
3049 1 80
3193 1 80
3098 1 80
3025 1 72
3082 1 70
3167 1 70
3122 1 67
3220 1 65
3080 1 65
3168 1 64
______________________
Total Entries >= 18
There is a requirement that there be at least one entry from each category in the top 10 (or top whatever it may be i.e. top 100), in this case there are 3 Categories.
Now all I need to do is to include at least one entry per category in the top 10. i.e. if all the top 10 scores are from Category 1, and there are 3 categories, I need to drop the 2 lowest scores from Category 1 and include the highest score entry for both Category 2 and 3.
As you can see from the results all the entries are from Category 1, so I need to drop EntryID's 3220, 3080 and 3168 from the resultset as they are the lowest scored, and include the highest scoring entry in Category 2 as well as the highest scoring entry in Category 3 so that the result looks something like this:
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3047 1 80
3048 1 80
3049 1 80
3193 1 80
3098 1 80
3025 1 72
3082 1 70
3167 1 70
3122 1 67
3019 3 60
3800 2 54
______________________
Total Entries >= 17
Same thing goes for the following scenario, let's look at the top 5 instead of top 10 to make it a little easier on the eye, as you can see in this example the Top 5 scores exclude entries from Category 2
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3019 3 60
______________________
Total Entries >= 7
In this case entries 3225 and 3045 needs to drop as they are the lowest scored entries (3047 needs to be included as even though it's the lowest scored entry I need an entry from all categories in the result) and I need to include the highest scored entry from Category 2, I would expect something like this:
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3019 3 60
3800 2 54
______________________
Total Entries >= 6
And then there may be the scenario where there may not be an entry into a specific category, let say for example no Category 2 entries so the result should still have the top 5 as with the original result set for the top 5 above (included below as reference)
EntryID CategoryID Score
3036 1 85
3159 1 85
3039 1 84
3146 1 83
3225 1 82
3045 1 82
3019 3 60
______________________
Total Entries >= 7
Please excuse if I'm repeating myself, I'm just trying to make it clear to understand ;)
I really Appreciate the help!
As I can see it, you need to rank your rows in a more sophisticated way, so that entries that are the top ones in every category are included regardless of their values, and entries that are not the top ones are included according to their overall rankings.
What I'm about to suggest may not be the most efficient solution, but it should work and, if nothing else can, might inspire someone else to come up with something better:
WITH ranked1 AS (
SELECT
*,
RankByCategory = DENSE_RANK() OVER (
PARTITION BY CategoryID
ORDER BY Score DESC
)
FROM YourTable
),
ranked2 AS (
SELECT
*,
FinalRank = DENSE_RANK() OVER (
ORDER BY
CASE RankByCategory WHEN 1 THEN 1 ELSE 2 END,
Score DESC
)
FROM ranked1
)
SELECT
EntryID,
CategoryID,
Score
FROM ranked2
WHERE FinalRank <= #top_n
;
The first CTE is ranking rows by categories, thus letting us find out which entries become the top ones in their respective categories. The next step (second CTE) is about obtaining global rankings, this time taking into account whether an entry is the top one in its category or not. The category top values receive lower rankings and thus are ensured to be included in the final results. (Of course, you need to make sure that the number of categories is not greater than the number of distinct values you want to receive in the output.)
Here's a live example at SQL Fiddle to play with.