Выберите самую низкую цену для каждой группы - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть такая таблица:

+----+-----+-------+-----------+
| id | pid | price | available |
+----+-----+-------+-----------+
| 1  | 1   | 100   | 0         |
| 2  | 1   | 110   | 1         |
| 3  | 1   | 200   | 1         |
| 4  | 2   | 150   | 5         |
| 5  | 2   | 160   | 0         |
+----+-----+-------+-----------+

В: Мне нужно выбрать полную строку с наименьшим price и available > 0 для каждого pid.

Ожидаемый результат:

+----+-----+-------+-----------+
| id | pid | price | available |
+----+-----+-------+-----------+
| 2  | 1   | 110   | 1         |
| 4  | 2   | 150   | 5         |
+----+-----+-------+-----------+

Я уже сделал это с помощью вложенного запроса, используя «group by id», потому что предложение order by не делает работать во вложенных запросах. Эта ссылка описывает, почему в подзапросах не работает order by


edit: , если две или более строки имеют одинаковую цену и доступны обе, выберите один с более высоким доступным номером.

+----+-----+-------+-----------+--------+
| id | pid | price | available |  sold  |
+----+-----+-------+-----------+--------+
| 1  | 1   | 100   |     0     |   200  |
| 2  | 1   | 110   |     1     |   2    |
| 3  | 1   | 110   |     4     |   20   |
| 4  | 1   | 110   |     4     |   50   |
| 5  | 1   | 200   |     1     |   20   |
| 6  | 2   | 150   |     5     |   20   |
| 7  | 2   | 160   |     0     |   20   |
+----+-----+-------+-----------+--------+

Ожидаемый результат:

+----+-----+-------+-----------+--------+
| id | pid | price | available |  sold  |
+----+-----+-------+-----------+--------+
| 4  | 1   | 110   |     4     |   50   |
| 6  | 2   | 150   |     5     |   20   |
+----+-----+-------+-----------+--------+

Ответы [ 2 ]

2 голосов
/ 22 апреля 2020

Один из вариантов - фильтрация с помощью коррелированного подзапроса:

select p.*
from prices p
where 
    p.available > 0
    and p.price = (
       select min(p1.price) from prices p1 where p1.pid = p.id and p1.available > 0
    )

Для производительности с этим запросом рассмотрите индекс на (pid, available, price).

0 голосов
/ 22 апреля 2020

Работает также с вложенными подзапросами, но здесь они вам не нужны

Это покажет вам все записи там, где у вас самая низкая цена

Так что, когда у вас было две записи для pid = 1, где диаметр был 110, вы бы увидели его.

Вы не указали, что делать с двумя или более рядами с минимальной ценой и доступными больше 0 . Поэтому, если вам нужен только один ряд для каждого pid, вы должны сгруппировать результат и решить, какой из доступных вариантов выбрать, с помощью функции агрегирования .

CREATE TABLE prices 
    (`id` int, `pid` int, `price` int, `available` int)
;

INSERT INTO prices 
    (`id`, `pid`, `price`, `available`)
VALUES
    (1, 1, 100, 0),
    (2, 1, 110, 1),
    (3, 1, 200, 1),
    (4, 2, 150, 5),
    (5, 2, 160, 0)
;
✓

✓
SELECT
`id`, p.`pid`, `price`, `available`
FROM prices p INNER JOIN 
(SELECT MIN(price)  minprice, pid FROm prices  WHeRE available > 0 GROUP BY pid) p1 
ON p1.minprice = p.price AND p.pid = p1.pid
id | pid | price | available
-: | --: | ----: | --------:
 2 |   1 |   110 |         1
 4 |   2 |   150 |         5

дБ <> скрипка здесь

...