Для версий MySQL под MySQL 8.0 вы можете использовать пользовательские переменные MySQL для имитации / эмуляции ROW_NUMBER()
Запрос
SELECT
t.product_id
, t.price
, (@ROW_NUMBER := @ROW_NUMBER + 1) AS ROW_NUMBER
FROM
t
CROSS JOIN (SELECT @ROW_NUMBER := 0) AS init_user_variable
ORDER BY
t.price ASC
Результат
| product_id | price | ROW_NUMBER |
| ---------- | ----- | ---------- |
| 1 | 10 | 1 |
| 2 | 50 | 2 |
| 3 | 100 | 3 |
| 4 | 400 | 4 |
| 5 | 900 | 5 |
| 6 | 8999 | 6 |
Когда мы получим ROW_NUMBER, мы можем использовать его в сочетании с ROW_NUMBER <= CEIL(((SELECT COUNT(*) FROM t) * 0.33));
, который работает следующим образом
(SELECT COUNT(*) FROM t)
=> Подсчитывает и возвращает6(SELECT COUNT(*) FROM t) * 0.33)
Вычисляет 33% от 6, что составляет 1,98, и возвращает егоCEIL(..)
Возвращает наименьшее целочисленное значение, которое больше или равно 1,98, что в данном случае равно 2 ROW_NUMBER <= 2
Таким образом, последний фильтр - это.
Запрос
SELECT
a.product_id
, a.price
FROM (
SELECT
t.product_id
, t.price
, (@ROW_NUMBER := @ROW_NUMBER + 1) AS ROW_NUMBER
FROM
t
CROSS JOIN (SELECT @ROW_NUMBER := 0) AS init_user_variable
ORDER BY
t.price ASC
) AS a
WHERE
ROW_NUMBER <= CEIL(((SELECT COUNT(*) FROM t) * 0.33));
Результат
| product_id | price |
| ---------- | ----- |
| 1 | 10 |
| 2 | 50 |
см. демо
Чтобы получить максимум, просто добавьте ORDER BY a.price DESC LIMIT 1
Запрос
SELECT
a.product_id
, a.price
FROM (
SELECT
t.product_id
, t.price
, (@ROW_NUMBER := @ROW_NUMBER + 1) AS ROW_NUMBER
FROM
t
CROSS JOIN (SELECT @ROW_NUMBER := 0) AS init_user_variable
ORDER BY
t.price ASC
) AS a
WHERE
ROW_NUMBER <= CEIL(((SELECT COUNT(*) FROM t) * 0.33))
ORDER BY
a.price DESC
LIMIT 1;
Результат
| product_id | price |
| ---------- | ----- |
| 2 | 50 |
см. демо