SQL Summary of revenues by region (in ranked order from highest to lowest, calculate % of total for each region) - sql

Summary of revenues by region (in ranked order from highest to lowest, calculate % of total for each region). Basically, I am trying to write a query that will show the revenues of each region relative to the total revenue.
I am using SQL in Microsoft Access.
My table has the following columns: ID, Region, Revenue
There are 3 regions: West, Central, East
Heres what I have so far:
SELECT Region, Sum(Revenue) AS TotalRevenue
FROM Sales
GROUP BY Region
ORDER BY Sum(Revenue) DESC
Any help would be greatly appreciated

Try this:
SELECT Region, SUM(Revenue) AS TotalRevenue,
(SUM(Revenue)/(SELECT Sum(Revenue) FROM Sales)) AS percentage
FROM Sales
GROUP BY Region
ORDER BY Sum(Revenue) DESC

This is one way that I'd offer, for only three regions its really overkill, but it should work.
SELECT Region, Sum(Revenue) AS TotalRevenue, Sum(Revenue)/x.allRegionRevenue
FROM Sales s,
inner join (select sum(revenue) allRegionRevenue)) x
on s.revenue*0 = x.allRegionRevenue*0
GROUP BY Region
ORDER BY Sum(Revenue) DESC
*Edit: * Modified this a bit as Access doesn't support actual "cross join" syntax, but I think we can "fake" it with an inner join on a condition that's always true - klugey trick here is merely to multiply references from each to zero forcing all recs to match. Hope this helps.

Related

How to calculate AVG into left join between 2 tables?

I have to calculate the avg of gross revenue on bigquery (the key is item_id).
SELECT
t0.order_create_date AS day,
t0.site_country AS country,
p0.product_brand AS brand,
p0.product_gender AS gender,
p0.product_department AS department,
t0.item_qty AS items_sold,
t0.item_sale_price AS gross_revenue,
t0.item_net_price AS net_revenue,
FROM
`transactions` t0
LEFT JOIN
`products` p0
ON
t0.item_id = p0.item_id
ORDER BY
country,
day ASC
I tried this :
SELECT
t0.order_create_date AS day,
t0.site_country AS country,
p0.product_brand AS brand,
p0.product_gender AS gender,
p0.product_department AS department,
t0.item_qty AS items_sold,
t0.item_sale_price AS gross_revenue,
AVG(t0.item_sale_price) AS average_value,
t0.item_net_price AS net_revenue,
FROM
`transactions` t0
LEFT JOIN
`products` p0
ON
t0.item_id = p0.item_id
ORDER BY
country,
day ASC
Biquery result:
SELECT list expression references t0.order_create_date which is neither grouped nor aggregated at [2:3]
The problem is that you didn't aggregate or by all the other columns, except the average_value one. Here you can read more about Group By.
From the names of the columns you are creating, I suppose you also want to have other information such as gross and net revenue. You would have to use some aggregate function on them too, otherwise the error would continue.
Something like the following should probably work:
SELECT
t0.order_create_date AS day,
t0.site_country AS country,
p0.product_brand AS brand,
p0.product_gender AS gender,
p0.product_department AS department,
sum(t0.item_qty) AS items_sold,
sum(t0.item_sale_price) AS gross_revenue,
AVG(t0.item_sale_price) AS average_value,
sum(t0.item_net_price) AS net_revenue,
FROM
transactions t0
LEFT JOIN
products p0
ON
t0.item_id = p0.item_id
GROUP BY
day,
country,
brand,
gender,
department
ORDER BY
country,
day ASC

Querying revenue by percentile in googlesql

I'm trying to group companies and their revenues by percentiles (>90% as Top, 50-90% as middle, < 50% as bottom, in googlesql.
Table format for revenue_table:
|company | product | revenue |
------------------------------
I'm trying out doing a cross join to split these companies up:
SELECT
company,
SUM(revenue) as revenue,
CASE
WHEN SUM(revenue) > Percentile90_Max THEN "Top"
WHEN SUM(revenue) >= Percentile50_Max THEN "Middle"
ELSE "Bottom"
END as percentile_section,
Percentile50_Max,
Percentile90_Max,
FROM revenue_table
CROSS JOIN
(SELECT
APPROX_QUANTILES(revenue,100)[offset(50)] As Percentile50_Max,
APPROX_QUANTILES(revenue,100)[offset(90)] As Percentile90_Max
FROM
(SELECT
company,
SUM(revenue) as revenue
FROM revenue_table
GROUP BY 1
)
)
GROUP BY 1,4,5
Order by 2 desc
The code above currently works, but gets broken once I change my main select statement to:
SELECT
company,
--SUM(revenue) as revenue,
CASE
WHEN SUM(revenue) > Percentile90_Max THEN "Top"
WHEN SUM(revenue) >= Percentile50_Max THEN "Middle"
ELSE "Bottom"
END as percentile_section,
--Percentile50_Max,
--Percentile90_Max,
... same code here
GROUP BY 1
Ideally my end result should just be Company + percentile_section.
How should I do this without doing another subquery? Or is subquery really the only way to go in terms of querying efficiency?
Thank you!
You should be able to calculate the quantiles as part of the aggregation, so no subquery should be necessary:
SELECT company, SUM(revenue) as revenue,
(CASE WHEN SUM(revenue) > (APPROX_QUANTILES(SUM(revenue), 100) OVER ())[offset(90)] THEN 'Top'
WHEN SUM(revenue) >= (APPROX_QUANTILES(SUM(revenue), 100) OVER ())[offset(50)] THEN 'Middle'
ELSE 'Bottom'
END) as percentile_section
FROM revenue_table
GROUP BY 1
Order by 2 desc

Group by 4 different levels and total numeric field

I'm querying a financial database that has the following information:
Company ID
Fiscal Year
Fiscal Period
Account
Amount
I want to group the data by the first four fields and show a grouped total of amount.
I tried the GROUP BY but that doesn't seem to work.
In my screenshot, I'm trying to get rows 1-10 to show as one line, as all the information is the same except for the amount.
Here's my code:
SELECT Erp.GLJrnDtl.Company, Erp.GLJrnDtl.FiscalYear,
Erp.GLJrnDtl.FiscalPeriod, Erp.GLJrnDtl.BalanceAcct,
Erp.GLJrnDtl.BookDebitAmount - Erp.GLJrnDtl.BookCreditAmount AS Amount
FROM Erp.GLJrnDtl INNER JOIN
Erp.GLPeriodBal ON Erp.GLJrnDtl.Company =
Erp.GLPeriodBal.Company AND Erp.GLJrnDtl.FiscalYear =
Erp.GLPeriodBal.FiscalYear AND Erp.GLJrnDtl.FiscalPeriod =
Erp.GLPeriodBal.FiscalPeriod AND
Erp.GLJrnDtl.BalanceAcct =
Erp.GLPeriodBal.BalanceAcct
WHERE (Erp.GLJrnDtl.FiscalYear >= 2018) AND (Erp.GLJrnDtl.Company
= N'011') and (Erp.GLJrnDtl.SegValue1 = N'310050')
GROUP BY Erp.GLJrnDtl.Company, Erp.GLJrnDtl.FiscalYear,
Erp.GLJrnDtl.FiscalPeriod, Erp.GLJrnDtl.BalanceAcct,
Erp.GLJrnDtl.PostedDate, Erp.GLJrnDtl.BookDebitAmount,
Erp.GLJrnDtl.BookCreditAmount, Erp.GLJrnDtl.SegValue1,
Erp.GLPeriodBal.BalanceAmt
select company_id, fiscal_year, fiscal_period, account, sum(amount)
from table group by company_id, fiscal_year, fiscal_period, account
You need to leave out the field you want to aggregate outside the group by line
Please explain why this does not do what you want:
select Company_ID, Fiscal_Year, Fiscal_Period, Account, sum(Amount)
from t
group by Company_ID, Fiscal_Year, Fiscal_Period, Account;
This is the "obvious" query. The query in the image is much more complicated.

SQL subquery to calculate frequency over average frequency

I want to create a chart that will represent the performance of some stores.
The x axis will represent the total revenue of the store over the average revenue of all the stores.
And the y axis will represent the average frequency the customers of a specific store visit this store over the average frequency all the customers visit all the stores.
This is what I have tried :
select
distinct [Order].shop_id
, SUM(total) /((select AVG(o.shopTotal)
from
(
select
distinct shop_id , SUM(total) as shopTotal
from [Order]
group by shop_id
)o)*0.1) as revPerAvgRev
,COUNT(distinct orderno) /((select AVG(orders)
from
(
select
distinct shop_id , room, COUNT(distinct orderno) as orders
from [Order]
group by shop_id , room
)o)*0.1) as freqPerAvgFreq
from [Order]
group by [order].shop_id
order by revPerAvgRev desc
select distinct shop_id ,room , count(distinct orderno)
from [Order]
group by shop_id , room
I believe the average frequency that the customers visit the stores is ok.
But I cannot manage to calculate correclty the average frequency each customer visit the store.
Note: Each customer only visits one store.
It is a little difficult to follow exactly what you want. You ask for frequencies but the code sample is showing revenue. You can get the proportion of revenue by using a window function to calculate the total:
select shop_id, shopTotal,
cast(shopTotal as float)/ sum(shopTotal) over () as Revenue,ProportionOfTotal,
numvisits,
cast(numvisits as float) / sum(numvisits) over () as VisitsProportionOfTotal
from (select shop_id , SUM(total) as shopTotal, count(*) as numvisits
from [Order]
group by shop_id
) s

Select highest profit from each year SQL

How do I obtain the highest value for each year within a table. So let's say we have a table movies and I want to find the highest profiting film for each year.
This is my attempt so far:
SELECT year, MAX(income - cost) AS profit, title
FROM Movies m, Movies m2
GROUP BY year
I am pretty certain it is going to need some sub selects but I can't visualise what I need to do. I was also thinking probably some sort of distinct option to rule out duplicate years.
Title Year Income Cost Length
A 2000 10 2 2
B 2000 9 7 2
So from this the expected result would be
Title Year Profit
A 2000 8
I'm guessing slightly at what you want, but since you've not specified any RDBMS a generic solution would be:
SELECT m.Year, (m.Income - m.Cost) AS Profit, m.Title
FROM Movies m
INNER JOIN
( SELECT m.Year, MAX(m.Income - m.Cost) AS Profit
FROM Movies
GROUP BY m.Year
) MaxProfit
ON MaxProfit.Year = m.Year
AND MaxProfit.Profit = (m.Income - m.Cost)
ORDER BY m.Year
You can also do this using analytic functions if your DBMS permits. e.g. SQL-Server
WITH MovieCTE AS
( SELECT m.Year,
Profit = (m.Income - m.Cost),
m.Title,
RowNumber = ROW_NUMBER() OVER(PARTITION BY m.Year ORDER BY (m.Income - m.Cost) DESC)
FROM Movies
)
SELECT year, Profit, Title
FROM MovieCTE
WHERE RowNumber = 1
It is possible I have misunderstood your exact criteria, but I am sure the same priciples can be applied, you will just need to alter the grouping and the join in the first example, or the partition by in the second.
select m1year,m1profit,title
from
(
(select year as m1year, max(income- cost) as m1profit from movies group by year) m1
join
(select m2year, (income-cost) as m2profit ,title as profit from movies) m2
on
m1profit = m2profit
) m
This will give the highest profit movie for each year, and choose the first title in the event of a tie:
select a.year, a.profit,
(select min(title) from Movies where year = a.year and income - cost = a.profit) as title
from (
select year, max(income - cost) as profit
from Movies -- title, year, cost, income, number
group by year
) as a
order by year desc