Выбор столбцов с группировкой и без нее

#sql

#sql

Вопрос:

Наличие таблицы1

 id | productname | store   | price  
-----------------------------------  
1  |      name a | store 1 |     4  
2  |      name a | store 2 |     3  
3  |      name b | store 3 |     6  
4  |      name a | store 3 |     4  
5  |      name b | store 1 |     7  
6  |      name a | store 4 |     5  
7  |      name c | store 3 |     2  
8  |      name b | store 6 |     5  
9  |      name c | store 2 |     1  
  

Мне нужно получить все столбцы, но только строки с самой
низкой ценой.
Необходимый результат:

 id | productname | store   | price  
-----------------------------------  
2  |      name a | store 2 |     3  
8  |      name b | store 6 |     5  
9  |      name c | store 2 |     1  
  

Моя лучшая попытка:

 SELECT ProductName, MIN(Price) AS minPrice  
FROM Table1  
GROUP BY ProductName  
  

Но тогда мне нужно ID и STORE для каждой строки.

Комментарии:

1. Это GROUP BY Id, ProductName, Store то, что вы хотите?

2. Что, если две строки имеют одинаковую цену?

Ответ №1:

Попробуйте это

 select p.* from  Table1 as p inner join 
(SELECT ProductName, MIN(Price) AS minPrice    FROM Table1      GROUP BY ProductName) t 
on p.productname  = t.ProductName and p.price = t.minPrice    
  

Ответ №2:

 Select ID,ProductName,minPrice
from
(
SELECT ProductName, MIN(Price) AS minPrice
FROM Table1
GROUP BY ProductName
) t
join Table1 t1 on t.ProductName = t1.ProductName
  

Комментарии:

1. Это приведет к дублированию, когда две цены будут самыми низкими для продукта.

2. затем используйте distinct или вместо group by over (раздел по имени продукта или по имени заказа), имеющий = 1

Ответ №3:

Вы не упомянули свой диалект SQL, но большинство СУБД поддерживают стандартные «оконные агрегированные функции» SQL:

 select *
from
  ( select t.*,
       RANK() OVER (PARTITION BY ProductName ORDER BY Price) as rnk 
    from table1 as t
  ) as dt
where rnk = 1
  

Если несколько магазинов получили одинаковую самую низкую цену, все они будут возвращены. Если вам нужен только один магазин, вам нужно переключиться на ROW_NUMBER вместо RANK или добавить столбцы в ORDER BY .

Ответ №4:

Я думаю, что этот запрос должен выполнить:

 select min(t.id) id
,      t.productname
,      t.price
from   table1 t
join
( select min(price) min_price
  ,      productname
  from   table1
  group
  by     productname
) v
on     v.productname = t.productname
and    v.price = t.min_price
group
by     t.productname
,      t.price
  

Он определяет самую низкую цену за продукт и извлекает каждую строку в базовой таблице ( t ). Это позволяет избежать дублирования путем группировки productname и выбора наименьшего id .

Ответ №5:

Это должно сработать для вас:

 SELECT * FROM `Table1` AS `t1`
WHERE (
   SELECT count(*) FROM `Table1` AS `t2` WHERE `t1`.`productName` = `t2`.`productName` AND `t2`.`price` < `t1`.`price`) < 1
  

Проверьте SQLFiddle

Но если у вас есть одинаковые товары с одинаковой минимальной ценой в двух магазинах, вы получите их оба в результате вывода