I have a table that tracks violations
for a student. I want to count the number of violations and select top 2 violators from each class. The query would look like this
SELECT *
FROM
( SELECT "people"."id", "name", "class",
ROW_NUMBER() OVER (PARTITION BY "class" ORDER BY COUNT("violation") DESC) AS "v"
FROM "people"
INNER JOIN "discipline" on ("discipline"."people_id" = "people"."id")
GROUP BY "people"."id", "name", "class"
) AS "v_table"
WHERE v < 3
The query seems inefficient because it sorts the count first with ORDER BY
and then assigns a ROW_NUMBER
. If I already have it sorted over a partition, how can I skip the ROW_NUMBER assignment & get the top 2.
Update :
Adding data tables & SQL fiddle (actually violation column is redundant, simply an entry in discipline table means that there's been a violation. If I remove it, should the Count
be done on "discipline"."people_id"
? like this )
Discipline People
------------------------- --------------
id people_id violation id name class
1 1 True 1 Rob A
2 1 True 2 Jen B
3 2 True 3 Tom C
4 3 True 4 Ted A
5 4 True 5 Tim A
6 1 True ...
7 4 True
...
Using PostgreSQL 9.3
COUNT(violation)
values stored somewhere?COUNT
followed byORDER BY
insideOVER()
count the values first and then sort them in descending order over partitionclass
before passing it on to theROW_NUMBER
function? The latter simply assigns a consecutive numeric id. Excuse my ignorance, since I'm new to SQL & trying to wrap my head around the concepts.