可以说我有一个包含许多这样的行的表:
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
我正在考虑UNION使用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)
我收到错误消息是因为[公司]和[订单日期]
在HAVING子句中无效,因为它不在聚合函数或GROUP BY子句中。
我怎样才能解决这个问题?
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 快速答案(基于@Nikola Markovinovi膰答案):
; 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)
您可以使用窗口功能一次完成此操作:
; 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)