SQL как получить максимальную цену на 33% самых дешевых продуктов - PullRequest
0 голосов
/ 15 марта 2019

Мне нужно, чтобы получить максимальную цену на 33% самых дешевых продуктов.Моя идея такая.Конечно, этот код является лишь примером.Мне нужно использовать подзапросы.

select max((select price from products order by preco limit 33%  ))  as result from products

Например,

  product_id    price
      1          10
      2          50
      3          100
      4          400
      5          900
      6         8999

Мне нужен запрос, который возвращает 50, поскольку 33% строк равно 2, а максимальное значение 2(33%) строк - 50.

Ответы [ 4 ]

0 голосов
/ 15 марта 2019

Если ваша версия поддерживает оконные функции, вы можете использовать NTILE(3), чтобы разделить строки на три группы, упорядоченные по price.Первая группа будет содержать (около) «33%» самых низких цен.Тогда вам просто нужно выбрать значение MAX из этой группы:

with cte as (
  select price, ntile(3) over (order by price) as ntl
  from products
)
select max(price)
from cte
where ntl = 1

Демо

До MySQL 8.0 я использовал бы временную таблицу с AUTO_INCREMENTколонка:

create temporary table tmp (
  rn int auto_increment primary key,
  price decimal(10,2)
);
insert into tmp(price)
  select price from products order by price;

set @max_rn = (select max(rn) from tmp);

select price
from tmp
where rn <= @max_rn / 3
order by rn desc
limit 1;

Демо

0 голосов
/ 15 марта 2019

Очевидно, что есть несколько подходов к этому, но вот как я бы это сделал.

  1. Просто получите счет на столе.Это позволит мне выбрать максимальную цену самых дешевых 33% товаров.Допустим, это вернуло n записей.Треть этого будет n/3.Здесь вы можете округлить или вверх, или вниз, но в случае дроби нужно округлить.
  2. Тогда мой запрос будет выглядеть как SELECT * FROM products ORDER BY price ASC LIMIT 1 OFFSET n/3.Это вернуло бы мне одну запись с минимальными вычислениями и просмотром на стороне MySQL.
0 голосов
/ 15 марта 2019

Для версий 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    |

см. демо

0 голосов
/ 15 марта 2019

В MySQL 8+ вы бы использовали оконные функции:

select avg(precio)
from (select p.*, row_number() over (order by precio) as seqnum,
             count(*) over () as cnt
      from products p
     ) p
where seqnum <= 0.33 * cnt;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...