Reputation: 863
I have the following tables:
Account (id, name)
Solution (id, name)
Sales (solution_id, account_id, month, year, amount)
I need to calculate the monthly sales of each account in a specific period:
SELECT
to_char(make_date(sales.year, sales.month, 1), 'YYYY-MM') AS period,
acc.id AS account_id,
acc.name AS account_name,
COALESCE(SUM(sales.net_sales), 0) AS amount
FROM
(SELECT *
FROM sales
WHERE make_date(year, month, 1) >= FROM_DATE
AND make_date(year, month, 1) <= TO_DATE) sales
INNER JOIN account acc.id = sales.account_id
GROUP BY sales.year, sales.month
ORDER BY sales.year, sales.month ASC
I can now calculate the total sales, in the period in the range:
SELECT
to_char(make_date(sales.year, sales.month, 1), 'YYYY-MM') AS period,
acc.id AS account_id,
acc.name AS account_name,
COALESCE(SUM(sales.net_sales), 0) AS amount
FROM
(SELECT *, COALESCE(SUM(net_sales) OVER (PARTITION BY client_id), 0) AS total
FROM sales
WHERE make_date(year, month, 1) >= FROM_DATE
AND make_date(year, month, 1) <= TO_DATE) sales
INNER JOIN account acc.id = sales.account_id
GROUP BY sales.year, sales.month
ORDER BY sales.year, sales.month ASC
Is there a way to rank the total sales in order to get only the n
top account in the selected period?
Upvotes: 0
Views: 285
Reputation: 1270713
Your queries are a bit of a mess. The first is not syntactically correct. I think you can simplify and the intention is:
SELECT to_char(make_date(s.year, s.month, 1), 'YYYY-MM') AS period,
a.id AS account_id, a.name AS account_name,
COALESCE(SUM(s.net_sales), 0) AS amount,
SUM(SUM(s.net_sales)) OVER (PARTITION BY a.id) as total
FROM sales s INNER JOIN
account a
ON a.id = s.account_id
WHERE make_date(s.year, s.month, 1) >= FROM_DATE AND
make_date(s.year, s.month, 1) <= TO_DATE
GROUP BY s.year, s.month, a.id, a.name
ORDER BY s.year, s.month ASC;
If you want to rank by total sales (or monthly sales), then you can use dense_rank()
:
SELECT ym.*
FROM (SELECT to_char(make_date(s.year, s.month, 1), 'YYYY-MM') AS period,
a.id AS account_id, a.name AS account_name,
COALESCE(SUM(s.net_sales), 0) AS amount,
total,
DENSE_RANK() OVER (ORDER BY total DESC) as seqnum
FROM (SELECT s.*, SUM(s.net_sales) OVER (PARTITION BY client_id) as total
FROM sales s
) s INNER JOIN
account a
ON a.id = s.account_id
WHERE make_date(s.year, s.month, 1) >= FROM_DATE AND
make_date(s.year, s.month, 1) <= TO_DATE
GROUP BY s.year, s.month
) ym
WHERE seqnum <= 3
ORDER BY s.year, s.month ASC;
Upvotes: 2