Finding the avg. revenue for each sales rep - sql

I'd like to find the average monthly revenue for each sales owner--however my current query is taking the monthly total and just dividing it by the number of entries. Ultimately, I'd like to get the average by finding the total revenue for each month and then dividing it by the number of months and then eventually just finding the avg. of the past 6 months. Code as well as sample output below:
select activitydate, console_org_name, partneragency, partneradvertiser, org_sales_owner
,round(sum(gross_revenue_allocation)::numeric,2) as gross_revenue
,round(avg(sum(gross_revenue_allocation)) over (partition by org_sales_owner order by activitydate RANGE INTERVAL '5' MONTH PRECEDING)::numeric,2) as salesowner6monthavg
from data_provider_payout dpp
where activitydate >= '01/01/2019'
group by activitydate, console_org_name, partneragency, partneradvertiser, org_sales_owner

If I understand correctly, you need to aggregate by the month and the owner. That would be something like this:
select date_trunc('month', activitydate), org_sales_owner,
round(sum(gross_revenue_allocation)::numeric, 2) as gross_revenue,
round(avg(sum(gross_revenue_allocation)) over (
partition by org_sales_owner
order by min(activitydate)
range between interval '5 month' preceding and current_row
)
)::numeric, 2) as salesowner6monthavg
from data_provider_payout dpp
where activitydate >= '2019-01-01'
group by date_trunc('month', activitydate), org_sales_owner

Related

Write a query to display the total month wise sales amount received in the past 1 year

Table StructureWrite a query to display the total month wise sales amount received in the past 1 year . Display details like sales month, total sales amount. Give an alias_name as MONTH for retrieved sales month, TURN_OVER for sales amount. Sort the result by amount in descending order.
(Hint: Use table Sales_info. Use to_char for retrieving the month. Net amount for sales amount calculation. Use sysdate for calculation of past 1 year sales. DATA IS CASE-SENSITIVE.)
The code I have written is fetching me all years sales data.
select to_char(Sales_Date,'Month')"MONTH"
Net_Amount as Turn_Over
from Sales_Info
where Sales_Date= add_months(Sysdate,-12)
select to_char(Sales_Date,'MON')"MONTH",
Net_Amount as TURN_OVER
from Sales_Info
where Sales_Date > add_months(Sysdate,-12)
order by Net_Amount desc;
I'm not going to do your homework for you, but here is a list of things currently missing from your query:
a comma in the SELECT list
you need greater than, not equals because you want all dates "more than the moment it was a year ago"
you need to break your data into groups where each group has the same month, and you need to sum up all the data in that month, so your query needs to have the words GROUP BY and SUM in it..
The code I have written is fetching me all years sales data
No, the query as it stands will be giving you only the sales that happened at exactly the current date-time, one year ago, which is probably 0 records
You are pretty close. What you are missing is the GROUP BY and summary functions:
select to_char(Sales_Date, 'Month') as "MONTH"
SUM(Net_Amount) as Turn_Over
from Sales_Info
where Sales_Date= add_months(Sysdate, -12)
group by to_char(Sales_Date, 'Month');
Note that there are still some significant issues with the query. For instance, I really am not a fan of using month names for what you are doing. It leaves out the year. In fact, the above query is going to combine data from the current month and the same month last year.
I would instead go for complete months. And use trunc() instead:
select trunc(Sales_Date, 'MON') as "MONTH"
SUM(Net_Amount) as Turn_Over
from Sales_Info
where Sales_Date = add_months(trunc(Sysdate, 'MON'), -12) and
Sales_Date < trunc(sysdate, 'MON')
group by to_char(Sales_Date, 'Month')
order by "MONTH".
In a real-world environment, this would typically provided cleaner, more useful results. In addition, because the first column is actually the date, it is easy to sort by.
The ans will be :
Select to_char(Sales_Date , 'MON' ) as "MONTH" , sum(Net_Amount) as TURN_OVER
from Sales_Info
where Sales_Date > add_months(Sysdate , -12)
group by to_char(Sales_Date , 'MON')
order by TURN_OVER desc;

Using Date to find the inequality for sales than 500

I'm curious as to find the daily average sales for the month of December 1998 not greater than 100 as a where clause. So what I imagine is that since the table consists of the date of sales (sth like 1 december 1998, consisting of different date, months and year), amount due....First I'm going to define a particular month.
DEFINE a = TO_DATE('1-Dec-1998', 'DD-Month-YYYY')
SELECT SUBSTR(Sales_Date, 4,6), (SUM(Amount_Due)/EXTRACT(DAY FROM LAST_DAY(Sales_Date))
FROM ......
WHERE SUM(AMOUNT_DUE)/EXTRACT(DAY FROM LAST_DAY(&a)) < 100
I'm stuck as to extract the sum of amount due in the month of december 1998 for the where clause....
How can I achieve the objective?
To me, it looks like this:
select to_char(sales_date, 'mm.yyyy') month,
avg(amount_due) avg_value
from your_table
where sales_date >= trunc(date '1998-12-01', 'mm')
and sales_date < add_months(trunc(date '1998-12-01', 'mm'), 1)
group by to_char(sales_date, 'mm.yyyy')
having avg(amount_due) < 100;
WHERE clause can be simplified; it shows how to fetch certain period:
trunc to mm returns first day in that month
add_months to the above value (first day in that month) will return first day of the next month
the bottom line: give me all rows whose sales_date is >= first day of this month and < first day of the next month; basically, the whole this month
Finally, the where clause you used should actually be the having clause.
As long as the amount_due column only contains numbers, you can use the sum function.
Below SQL query should be able to satisfy your requirement.
Select SUM(Amount_Due) from table Sales where Sales_Date between '1-12-1998' and '31-12-1998'
OR
Select SUM(Amount_Due) from table Sales where Sales_Date like '%-12-1998'

Average over rolling date period

I have 4 dimensions, which one of them is date. I need to calculate for each date, the average in the last 30 days, per each dimension value.
I have tried to run average over a partition by the 4 dimensions in a form of:
SELECT
Date, Produce,Company, Song, Revenues,
Average(case when Date between Date -Interval '31' day and Date - Interval '1' Day then Revenues else null End) over (partition by Date,Company,Song,Revenues order by Date) as "Running Average"
From
Base_Table
I get only nulls with every aggregation I tried.
Help is appreciated. Thanks
You can try below -
SELECT
Date, Produce,Company, Song, Revenues,
Average(Revenues) over (partition by Company,Song rows between 30 preceding and current row) as "Running Average"
From
Base_Table

Selecting data with counts more than 4 in a month from a daily data

I am trying to count the monthly number of merchants (and the total transaction amount they've processed) who have made at least 4 transactions each month in the last 2 years from a table containing daily transaction by merchants.
My query is as follow:
SELECT trx.month, COUNT(trx.merchants), SUM(trx.amount)
FROM
(
SELECT
DATE_TRUNC('month', transactions.payment_date) AS month,
merchants,
COUNT(DISTINCT payment_id) AS volume,
SUM(transactions.payment_amount) AS amount
FROM transactions
WHERE transactions.date >= NOW() - INTERVAL '2 years'
GROUP BY 1, 2
) AS trx
WHERE trx.volume >= 4
My question is: will this query pull the right data? If so, is this the most efficient way of writing it or can I improve the performance of this query?
First of all we must think about the time range. You say that you want at least four transactions each month in the last 24 months. But you certainly don't require this for, say, October 2018, when running the query on October 10, 2018. Neither do you want to only look at only the last twenty days of October 2016 then. We would want to look at the complete October 2016 till the complete September 2018.
Next we want to make sure that a merchant had at least four transactions each month. In other words: they had transactions each month and the minimum number of transactions per month was four. We can use window functions to run over monthly transactions to check this.
select merchants, month, volume, amount
from
(
select
merchants,
date_trunc('month', payment_date) as month,
count(distinct payment_id) as volume,
sum(payment_amount) as amount,
count(*) over (partition by merchants) number_of_months,
min(count(distinct payment_id)) over (partition by merchants) min_volume
from transactions
where date between date_trunc('month', current_date) - interval '24 months'
and date_trunc('month', current_date) - interval '1 days'
group by merchants, date_trunc('month', payment_date)
) monthly
where number_of_months = 24
and min_volume >= 4
order by merchants, month;
This gives you the list of merchants fulfilling the requirements with their monthly data. If you want the number of merchants instead, then aggregate. E.g.
select count(distinct merchants), sum(amount) as total
from (...) monthly
where number_of_months = 24 and min_volume >= 4;
or
select month, count(distinct merchants), sum(amount) as total
from (...) monthly
where number_of_months = 24 and min_volume >= 4
group by month
order by month;
for get only the list of merchant you could use having for filter the result of the aggreated values for distinct number of payement_id and month
SELECT merchants
FROM transactions
WHERE transactions.date >= NOW() - INTERVAL '2 years'
GROUP BY merchants
having count(distinct DATE_TRUNC('month', transactions.payment_date)) =24
and COUNT(DISTINCT payment_id) >= 4
And for you updated question just a suggestion
You could join with the query that return the marchant with more then 4 volume for each month in tow year and filter the result for aggreated directly in subquery using having
SELECT trx.month, COUNT(trx.merchants), SUM(trx.amount)
FROM (
SELECT DATE_TRUNC('month', transactions.payment_date) AS month
, merchants
, COUNT(DISTINCT payment_id) AS volume
, SUM(transactions.payment_amount) AS amount
FROM transactions
INNER JOIN (
SELECT merchants
FROM transactions
WHERE transactions.date >= NOW() - INTERVAL '2 years'
GROUP BY merchants
having count(distinct DATE_TRUNC('month', transactions.payment_date)) =24
and COUNT(DISTINCT payment_id) >= 4
) A on A.merchant = transactions.merchant
WHERE transactions.date >= NOW() - INTERVAL '2 years'
GROUP BY 1, 2
HAVING volume >= 4
) AS trx

Average for partition bounded by last 7 days

I have a query spanned across last 30 days, which sums total revenue, however I also want along with sum of last 30 days, add average of last 7 days. I want something like this:
select
country
, avg(revenue) over (partition by country range between current_date - 7 and current_date) avg_revenue_last_7_days
, sum(revenue) total_revenue_30_days
from table
group by 1,2
Is it possible to get average for a smaller number of days than what aggregation is based on?
I want to avoid subqueries because the query already quite complex.
You don't need window functions for this, just conditional aggregation:
select country,
avg(case when datecol between current_date - 7 and current_date
then revenue
end) as avg_revenue_last_7_days,
sum(case when datecol between current_date - 30 and current_date
then revenue
end) as total_revenue_30_days
from table
group by country;