Aaron Anodide
Aaron Anodide

Reputation: 17186

What is the right way to combine grouping and ranking?

I already have a view which is a break down by day (ByDay in query below).

Now I want to filter it such that a row is included in the result if it's campaign is in the top 10 revenue generating campaigns.

I got what I wanted but I have a feeling I might skipped over the obvious/right way to do it in the process.

WITH T AS (
    SELECT
     ByDay.[Day]
    ,ByDay.[Campaign Name]
    ,ByDay.[Revenue USD]
    FROM ByDay
    WHERE ByDay.[Period]='Mar 2012'
),
TT AS (
    SELECT
     ByDay.[Campaign Name]
    ,SUM(ByDay.[Revenue USD]) [Sum Revenue USD]
    FROM ByDay
    WHERE ByDay.[Period]='Mar 2012'
    GROUP BY ByDay.[Campaign Name]
)
SELECT * FROM (
SELECT
     T.[Day]
    ,T.[Campaign Name]
    ,T.[Revenue USD]
    ,TT.[Sum Revenue USD]
    ,DENSE_RANK() OVER(ORDER BY TT.[Sum Revenue USD] DESC) AS R
    FROM T
    INNER JOIN TT ON T.[Campaign Name]=TT.[Campaign Name]
) TTT
WHERE R < 11
ORDER BY R

Is there a simpler way to get something like this?

Upvotes: 0

Views: 45

Answers (1)

Tim Schmelter
Tim Schmelter

Reputation: 460048

You could use SUM([Revenue USD])OVER(Partition By [Campaign Name]) to get the sum for each Campaign Name. Then you only need one CTE:

http://msdn.microsoft.com/en-us/library/ms189461.aspx

WITH T AS (
    SELECT
     ByDay.[Day]
    ,ByDay.[Campaign Name]
    ,ByDay.[Revenue USD]
    ,SUM(ByDay.[Revenue USD]) OVER(Partition By ByDay.[Campaign Name]) [Sum Revenue USD] 
    FROM ByDay
    WHERE ByDay.[Period]='Mar 2012'
)
SELECT * FROM (
SELECT
     T.[Day]
    ,T.[Campaign Name]
    ,T.[Revenue USD]
    ,T.[Sum Revenue USD]
    ,DENSE_RANK() OVER(ORDER BY T.[Sum Revenue USD] DESC) AS R
    FROM T
) TTT
WHERE R < 11
ORDER BY R

Upvotes: 3

Related Questions