I have monthly sales over specific car brands, and every month i want the max 5 car brands in relation to the sales. Then, next to each of these max brands, i want the number (if there is) that indicates how many times this specific brand was in the top five the previous 4 months.
Foe example, if table data is:
Timestamp | Brand | Sales
1/1/2012 | A | 23
1/1/2012 | B | 45
1/1/2012 | C | 11
1/1/2012 | D | 3
1/1/2012 | E | 55
1/1/2012 | F | 1
1/1/2012 | G | 22
---------------------------
1/2/2012 | A | 93
1/2/2012 | B | 35
1/2/2012 | C | 01
1/2/2012 | D | 100
1/2/2012 | E | 45
1/2/2012 | F | 77
1/2/2012 | G | 12
for a two month data, the query output for February (examining only Feb and Jan) would be :
Max_ Brand_Sales| Reappearance_Factor
--------------------------------------
E | 1
B | 1
D | 0
F | 0
A | 1
Select
c.Brand,
nvl(Count(p.Brand), 0) As Reappearance_Factor
From (
Select
Brand,
Rank () Over (Order By Sales Desc) as r
From
Sales
Where
Timestamp = Date '2012-02-01'
) c
left outer join (
Select
Brand,
Rank () Over (Partition By Timestamp Order By Sales Desc) as r
From
Sales
Where
Timestamp >= Date '2011-10-01' And
Timestamp < Date '2012-02-01'
) p
on c.Brand = p.Brand And p.r <= 5
Where
c.r <= 5
Group By
c.Brand
Try this:
1) Query that calculates monthly rank for every brand:
SELECT
s.Brand,
trunc(s.Timestamp,'MONTH') month_start,
rank() OVER (PARTITION BY trunc(s.Timestamp,'MONTH')
ORDER BY s.Sales DESC) as monthly_rank
FROM Sales s;
2) Query that outputs the top 5 brands for current month:
SELECT
t.Brand
FROM
(
SELECT
s.Brand,
trunc(s.Timestamp,'MONTH') month_start,
rank() OVER (PARTITION BY trunc(s.Timestamp,'MONTH')
ORDER BY s.Sales DESC) as monthly_rank
FROM Sales s
) t
WHERE monthly_rank <= 5
AND month_start = trunc(sysdate,'MONTH');
3) Query to calculate "Reappearance" for past 4 month
SELECT
t.Brand,
count(*) as top
FROM
(
SELECT
s.Brand,
trunc(s.Timestamp,'MONTH') month_start,
rank() OVER (PARTITION BY trunc(s.Timestamp,'MONTH')
ORDER BY s.Sales DESC) as monthly_rank
FROM Sales s
) t
WHERE monthly_rank <= 5
AND t.month_start BETWEEN add_months(sysdate, -1)
AND add_months(sysdate, -5)
GROUP BY t.Brand;
4) Last thing to do - LEFT JOIN
query 2 and 3
SQLFiddle here http://sqlfiddle.com/#!4/46770/65
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.