根据另一列上的条件从组中提取值

时间:2012-07-25 14:05:22

标签: sql sql-server tsql group-by pivot

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

表格包含项目。每个项目都属于一个类别并存储一些数值。

作为查询的结果,我希望每行代表一个类别。应该有三列:

  • 类别ID;
  • 每个类别ItemValue最高的项目的ID;
  • 每个类别ItemValue最低的项目的ID。

查询的性能很重要。我使用MS SQL Server。

3 个答案:

答案 0 :(得分:2)

对于SQL Server 2005+,您可以这样做:

;WITH CTE AS
(
    SELECT  *, 
            ROW_NUMBER() OVER(PARTITION BY CategoryId ORDER BY ItemValue DESC) MaxRN,
            ROW_NUMBER() OVER(PARTITION BY CategoryId ORDER BY ItemValue) 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;

以下是fiddle,您可以在其中测试此解决方案。

答案 1 :(得分:1)

我会尝试使用公用表表达式:

WITH CategoryHigh (High, ItemId, CategoryId) 
AS 
(
SELECT 
    ROW_NUMBER() OVER (PARTITION BY CategoryId ORDER BY ItemValue DESC) AS High,
    ItemId,
    CategoryId
FROM Items
),
CategoryLow (Low, ItemId, CategoryId) 
AS
(
SELECT 
    ROW_NUMBER() OVER (PARTITION BY CategoryId ORDER BY ItemValue) AS Low,
    ItemId,
    CategoryId
FROM Items
)
SELECT 
H.CategoryId,
L.ItemId AS LowItem,
H.ItemId AS HighItem
FROM CategoryHigh H
JOIN CategoryLow L ON H.CategoryId = L.CategoryId
WHERE H.High = 1 AND
      L.Low = 1

答案 2 :(得分:1)

试试这个:

;with 
cte as(
    select *,ROW_NUMBER() over(partition by [CategoryId] order by [ItemValue]) rownum
    from [Items] ),
cte1 as(select [CategoryId],MIN([ItemId]) [min_ItemId]
    from cte where rownum=1
    group by [CategoryId]),
cte2 as(
    select *,ROW_NUMBER() over(partition by [CategoryId] order by [ItemValue]) rownum
    from [Items] ),
cte3 as( 
    select [CategoryId],MAX([ItemId]) [max_ItemId]
    from cte2 C1
    where rownum=(select MAX(rownum) from cte C2 where C1.[CategoryId]=C2.[CategoryId])
    group by [CategoryId])
select A.[CategoryId],A.[min_ItemId],B.[max_ItemId] 
from cte1 A join cte3 B
on A.[CategoryId]=B.[CategoryId]