CREATE TABLE Items
(
ItemId INT NOT NULL,
CategoryId INT NOT NULL,
ItemValue INT NOT NULL
)
一个表包含项目。每个项目都属于一个类别并存储一些数值。
作为查询的结果,我希望每一行代表一个类别。应该有三列:
- 类别编号;
ItemValue
每个类别最高的项目的 ID ;ItemValue
每个类别最低的项目的 ID 。
查询的性能很重要。我使用 MS SQL Server。
CREATE TABLE Items
(
ItemId INT NOT NULL,
CategoryId INT NOT NULL,
ItemValue INT NOT NULL
)
一个表包含项目。每个项目都属于一个类别并存储一些数值。
作为查询的结果,我希望每一行代表一个类别。应该有三列:
ItemValue
每个类别最高的项目的 ID ;ItemValue
每个类别最低的项目的 ID 。查询的性能很重要。我使用 MS SQL Server。
对于 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;
这是一个小提琴,您可以在其中测试此解决方案。
我会尝试一个公用表表达式:
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
试试这个:
;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]