Diciamo che ho una tabella che contiene molte molte righe come questo:TSQL Selezionare Min & Max riga quando il raggruppamento
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
...
sto facendo una semplice query come questa:
SELECT max([Range]) AS 'Range'
, count(ID) AS 'Count'
, round(avg([Profit]), 2) AS 'AVG Profit'
FROM
Orders
GROUP BY
Range_begining
Dopo questo query viene eseguita ottengo risultati come questo:
Range Count AVG Profit
------------------------------------
(100-150) 2 40
(200-250) 1 40.2
(450-500) 1 -90
...
abbastanza semplice :)
012.351.Che cosa devo fare ora è quello di selezionare fila con minimo e massimo profitto dove conteggio è più grande di 10 (questo è un parametro)
sono stato in grado di ottenere il valore minimo con questo:
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
Stavo pensando di fare un UNION
per la query precedente con ORDER BY DESC, ma non è la soluzione migliore.
Cosa devo fare:
Select 2 file: uno con un minimo, secondo con la massima AVG profitto quando il raggruppamento per Range.
EDIT: Se aggiungo 2 colonne mossa alla mia tabella dati principale in questo modo:
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
...
E poi cercare di aggiungere ulteriori 2 condizioni come questo:
; 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][email protected]
AND (@from= '' OR [OrderDate]>[email protected])
AND (@to= '' OR [OrderDate]<[email protected])
)
select [range], [count], [avg profit]
from ordering
where (rn_max = 1 or rn_min = 1)
I ottenere un errore perché [Azienda] e [Data ordine]
non è valido nella clausola HAVING poiché non è contenuto in una funzione di aggregazione o nella clausola GROUP BY.
Come posso risolvere questo problema?
EDIT2 Funzionante!
; 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][email protected]
AND (@from= '' OR [OrderDate]>[email protected])
AND (@to= '' OR [OrderDate]<[email protected])
GROUP BY
Range_begining
HAVING COUNT(ID) > 10
)
select [range], [count], [avg profit]
from ordering
where (rn_max = 1 or rn_min = 1)
EDIT 3 Posso tornare un'altra colonna con la descrizione in questo modo:
Range AVG Profit Description
-------------------------------------------------
(200-250) 40.2 Max profit here
(450-500) -90 Min profit, well done
EDIT 4 Risposte rapide (sulla base di @Nikola Markovinović risposta):
; 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][email protected]
AND (@from= '' OR [OrderDate]>[email protected])
AND (@to= '' OR [OrderDate]<[email protected])
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)
Assicuratevi di aggiungere il tag 'SQL' alle vostre domande per ottenere più attenzione. –