Группировка по и агрегатная функция - PullRequest
2 голосов
/ 07 июля 2010

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

Есть идеи, как мне этого добиться? Спасибо.

CREATE TABLE Fruits (
    [type] nvarchar(250),
    [variety] nvarchar(250),
    [price] money
)
GO

INSERT INTO Fruits VALUES ('Apple', 'Gala', 2.79)
INSERT INTO Fruits VALUES ('Apple', 'Fuji', 0.24)
INSERT INTO Fruits VALUES ('Apple', 'Limbertwig', 2.87)
INSERT INTO Fruits VALUES ('Orange', 'Valencia', 3.59)
INSERT INTO Fruits VALUES ('Pear', 'Bradford', 6.05)

SELECT type, MIN(price)
FROM   Fruits
GROUP BY [type]

Ответы [ 3 ]

1 голос
/ 07 июля 2010

Есть несколько способов сделать это, одно решение ниже.

SELECT F2.type, f2.variety, f2.price
FROM 
(
    SELECT type, min(price) as price
    FROM Fruits
    GROUP BY [type]
) as MinData
    INNER JOIN Fruits F2
        ON (MinData.type = Type = F2.Type
            AND MinData.price = F2.Price)

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

1 голос
/ 07 июля 2010

Использование:

SELECT f.*
  FROM FRUITS f
  JOIN (SELECT t.type,
               MIN(t.price) AS min_price
          FROM FRUITS t
      GROUP BY t.type) x ON x.type = f.type
                        AND x.min_price = f.price

Я полагаю, что вы используете SQL Server - если v2005 или новее, вы могли бы вместо этого использовать аналитические / ранг / оконные функции:

SELECT f.type, f.variety, f.price
  FROM (SELECT t.type, t.variety, t.price,
               ROW_NUMBER() OVER (PARTITION BY t.type ORDER BY t.price) AS rank
          FROM FRUITS t) f
 WHERE f.rank = 1
0 голосов
/ 07 июля 2010

Есть простой прием, который вы можете использовать для такого рода запросов, если ваша таблица имеет суррогатный первичный ключ. (На самом деле, вы можете сделать это без одного, но это более запутанно.)

Настройка:

if object_id('tempdb..#Fruits') is not null drop table #Fruits
create table #Fruits (
  [id] int identity(1,1) not null,
  [type] nvarchar(250),
  [variety] nvarchar(250),
  [price] money
)

insert into #Fruits ([type], [variety], [price])
select 'Apple', 'Gala', 2.79 union all
select 'Apple', 'Fuji', 0.24 union all
select 'Apple', 'Limbertwig', 2.87 union all
select 'Orange', 'Valencia', 3.59 union all
select 'Pear', 'Bradford', 6.05

А теперь SQL:

select * -- no stars in PROD!
from #Fruits a
where
   a.id in (
      select top 1 x.id
      from #Fruits x
      where x.[type] = a.[type]
      order by x.price
   )
...