このような多くの行を含むテーブルがあるとしましょう。
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つの行を選択します。1つは最小、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)
[Company]と[OrderDate]が原因でエラーが発生します
集計関数にもGROUPBY句にも含まれていないため、HAVING句では無効です。
どうすればこれを修正できますか?
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)