Reputation: 249
I have a table with 2 columns:
name
, percentage
I have a 100 rows in this table, and want to make a query that selects the 5 rows with the smallest percentage value and the 5 rows with the largest percentage value.
Normally I would do this with limit
and offset
but it will select only one of the outcome groups I seek. I wonder if there is a way of selecting both.
I have been looking for a solution for a while, and I thought about FETCH, but I don't really succeed in using right.
Upvotes: 2
Views: 124
Reputation: 656301
UNION ALL
(
SELECT name, percentage
FROM tbl
ORDER BY percentage
LIMIT 5
)
UNION ALL
(
SELECT name, percentage
FROM tbl
ORDER BY percentage DESC
LIMIT 5
);
You need parenthesis, to apply ORDER BY
and LIMIT
to nested SELECT
statements of a UNION
query. I quote the manual here:
ORDER BY
andLIMIT
can be attached to a subexpression if it is enclosed in parentheses. Without parentheses, these clauses will be taken to apply to the result of theUNION
, not to its right-hand input expression.
UNION
(without ALL
) would remove duplicates in the result. A useless effort if you don't expect dupes.
row_number()
SELECT name, percentage
FROM (
SELECT *
, row_number() OVER (ORDER BY percentage) AS rn_min
, row_number() OVER (ORDER BY percentage DESC) AS rn_max
FROM tbl
) x
WHERE rn_min < 6
OR rn_max < 6;
This collapses duplicates like UNION
would. Performance will be similar, probably a bit slower than the first one.
Either way, order by additional columns to break ties in a controlled manner. As is, you get arbitrary rows from groups of peers sharing the same percentage
.
Upvotes: 1