Задать вопрос
Shedal
@Shedal

[SQL] Как вычленить значение из группы на основании условия по другому столбцу?

CREATE TABLE Items
(
  ItemId INT NOT NULL,
  CategoryId INT NOT NULL,
  ItemValue INT NOT NULL
)


В таблице содержатся item'ы. У каждого item'а есть категория (CategoryId), а также, какое-то значение (ItemValue).


Нужно написать запрос, результат которого будет сгруппирован по категории и будет содержать следующие столбцы:

  • id категории;
  • id item'а с наименьшим ItemValue в категории;
  • id item'а с наибольшим ItemValue в категории.


Производительность важна.
  • Вопрос задан
  • 4776 просмотров
Подписаться 2 Оценить Комментировать
Решения вопроса 1
tonyzorin
@tonyzorin
select CategoryId,max(id_min_value),max(id_max_value)
from 
(select CategoryId,
case when ItemValue=min(ItemValue) over (partition by CategoryId) then ItemId end as id_min_value,
case when ItemValue=max(ItemValue) over (partition by CategoryId) then ItemId end as id_max_value 
from Items) Items
group by CategoryId
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
4dmonster
@4dmonster
SELECT     CatsMMV.CategoryId, CatsMMV.MinV, CatsMMV.MaxV, MinI.ItemId AS MinItemID, MaxI.ItemId AS MaxItemID
FROM         (SELECT     CategoryId, MIN(ItemValue) AS MinV, MAX(ItemValue) AS MaxV
                       FROM          Items
                       GROUP BY CategoryId) AS CatsMMV LEFT OUTER JOIN
                      Items AS MaxI ON CatsMMV.CategoryId = MaxI.CategoryId AND CatsMMV.MaxV = MaxI.ItemValue LEFT OUTER JOIN
                      Items AS MinI ON CatsMMV.CategoryId = MinI.CategoryId AND CatsMMV.MinV = MinI.ItemValue
Ответ написан
@HiltoN
Ну, например, так:

select * from Items a
where not exists (
    select 1 from Items b
     where b.CategoryId = a.CategoryId
       and b.ItemId <> a.ItemId
       and ((b.ItemValue > a.ItemValue) or 
            (b.ItemValue = a.ItemValue 
         and b.ItemId > a.ItemId)));
Ответ написан
Shedal
@Shedal Автор вопроса
Для полноты картины, вот ещё одно решение, похожее на решение tonyzorin:

WITH CTE AS
(
  SELECT
    *, 
    ROW_NUMBER() OVER(PARTITION BY CategoryId ORDER BY ItemValue DESC) MaxRN,
    ROW_NUMBER() OVER(PARTITION BY CategoryId ORDER BY ItemValue ASC) MinRN
  FROM Items
)
SELECT
  CategoryId, 
  MIN(CASE WHEN MaxRN = 1 THEN ItemId END) IdMaxValue,
  MIN(CASE WHEN MinRN = 1 THEN ItemId END) IdMinValue
FROM CTE
GROUP BY CategoryId
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы