2012-07-25 134 views
1
CREATE TABLE Items 
(
    ItemId INT NOT NULL, 
    CategoryId INT NOT NULL, 
    ItemValue INT NOT NULL 
) 

表中包含项目。每个项目都属于一个类别并存储一些数字值。基于另一列上的条件从组中提取值

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

  • category id;
  • 每个类别中具有最高ItemValue的项目的ID;
  • 每个类别具有最低ItemValue的项目的ID。

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

回答

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在那里你可以测试这个解决方案。

+0

这很好,谢谢! – 2012-07-25 14:30:55

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 
+0

谢谢,这个作品!虽然,拉马克的解决方案似乎表现更好,而且它也更短,所以我将他的答案标记为已接受。 – 2012-07-25 14:32:04

+0

是的,我很高兴看到他的回答,因为我开始时试图在一个CTE中同时具有Row_Number()函数,但是无法从此处开始工作。尽管感谢您的认可! – Aushin 2012-07-25 14:33:23

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] 
相关问题