可以说我有一个包含许多这样的行的表:
ID Range Range_begining Profit
----------------------------------------------------
1 (100-150) 100 -20
2 (200-250) 200 40.2
3 (100-150) 100 100
4 (450-500) 450 -90
...
我正在做一个简单的查询,像这样:
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
FROM
Orders
GROUP BY
Range_begining
运行此查询后,我得到如下结果:
Range Count AVG Profit
------------------------------------
(100-150) 2 40
(200-250) 1 40.2
(450-500) 1 -90
...
非常简单 :)
我现在需要做的是选择计数大于10的具有最小和最大利润的行(这是一个参数)
我能够通过此获得最小值:
SELECT TOP 1 [Range], [AVG Profit] FROM (
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
FROM
Orders
GROUP BY
Range_begining) X
WHERE
[Count]>10
ORDER BY
[AVG Profit] ASC --or DESC if I want max profit
我当时正在考虑使用ORDER BY DESC为上面的查询做一个
UNION
,但这不是最好的解决方案。我需要做什么:
选择2行:按范围分组时,第一行最少,第二行最大AVG利润。
编辑:
如果我将2个移动列添加到我的主数据表中,如下所示:
ID Range Range_begining Profit OrderDate Company
---------------------------------------------------------------------------------
1 (100-150) 100 -20 2012-01-02 1
2 (200-250) 200 40.2 2012-03-22 0
3 (100-150) 100 100 2012-02-05 0
4 (450-500) 450 -90 2012-05-12 1
...
然后尝试再添加2个这样的条件:
; with ordering as (
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
, row_number() over (order by avg([Profit])) rn_min
, row_number() over (order by avg([Profit]) desc) rn_max
FROM
Orders
GROUP BY
Range_begining
HAVING COUNT(ID) > 10
AND [Company]=@company
AND (@from= '' OR [OrderDate]>=@from)
AND (@to= '' OR [OrderDate]<=@to)
)
select [range], [count], [avg profit]
from ordering
where (rn_max = 1 or rn_min = 1)
我收到错误消息是因为[公司]和[订单日期]
我怎样才能解决这个问题?
EDIT2
得到它的工作!
; with ordering as (
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
, row_number() over (order by avg([Profit])) rn_min
, row_number() over (order by avg([Profit]) desc) rn_max
FROM
Orders
WHERE
[Company]=@company
AND (@from= '' OR [OrderDate]>=@from)
AND (@to= '' OR [OrderDate]<=@to)
GROUP BY
Range_begining
HAVING COUNT(ID) > 10
)
select [range], [count], [avg profit]
from ordering
where (rn_max = 1 or rn_min = 1)
编辑3
我可以返回另一个描述如下的列:
Range AVG Profit Description
-------------------------------------------------
(200-250) 40.2 Max profit here
(450-500) -90 Min profit, well done
编辑4
快速答案(基于@NikolaMarkovinović答案):
; with ordering as (
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
, row_number() over (order by avg([Profit])) rn_min
, row_number() over (order by avg([Profit]) desc) rn_max
FROM
Orders
WHERE
[Company]=@company
AND (@from= '' OR [OrderDate]>=@from)
AND (@to= '' OR [OrderDate]<=@to)
GROUP BY
Range_begining
HAVING COUNT(ID) > 10
)
SELECT
CASE WHEN rn_max=1 THEN 'This is max' ELSE 'Min' END AS 'Description'
,[range]
,[count]
,[avg profit]
FROM ordering
WHERE (rn_max = 1 or rn_min = 1)
最佳答案
您可以使用window functions一次完成操作:
; with ordering as (
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
, row_number() over (order by avg([Profit])) rn_min
, row_number() over (order by avg([Profit]) desc) rn_max
FROM
Orders
GROUP BY
Range_begining
HAVING COUNT(ID) > 10
)
select [range], [count], [avg profit],
case when rn_max = 1
then 'Max profit'
else 'Min profit'
end Description
from ordering
where (rn_max = 1 or rn_min = 1)
And here is Sql Fiddle example。
关于sql - TSQL分组时选择“最小和最大”行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12001783/