How to calculate AVG into left join between 2 tables? - sql

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

Related

Combining multiple queries

I want a table with all customers and their last charge transaction date and their last invoice date. I have the first two, but don't know how to add the last invoice date to the table. Here's what I have so far:
WITH
--Last customer transaction
cust_trans AS (
SELECT customer_id, created
FROM charges a
WHERE created = (
SELECT MAX(created) AS last_trans
FROM charges b
WHERE a.customer_id = b.customer_id)),
--All customers
all_cust AS (
SELECT customers.id AS customer, customers.email, CAST(customers.created AS DATE) AS join_date, ((1.0 * customers.account_balance)/100) AS balance
FROM customers),
--Last customer invoice
cust_inv AS (
SELECT customer_id, date
FROM invoices a
WHERE date = (
SELECT MAX(date) AS last_inv
FROM invoices b
WHERE a.customer_id = b.customer_id))
SELECT * FROM cust_trans
RIGHT JOIN all_cust ON all_cust.customer = cust_trans.customer_id
ORDER BY join_date;
This should get what you need. Notice each individual subquery is left-joined to the customer table, so you always START with the customer, and IF there is a corresponding record in each subquery for max charge date or max invoice date, it will be pulled in. Now, you may want to apply a COALESCE() for the max dates to prevent showing nulls, such as
COALESCE(maxCharges.LastChargeDate, '') AS LastChargeDate
but your call.
SELECT
c.id AS customer,
c.email,
CAST(c.created AS DATE) AS join_date,
((1.0 * c.account_balance) / 100) AS balance,
maxCharges.LastChargeDate,
maxInvoices.LastInvoiceDate
FROM
customers c
LEFT JOIN
(SELECT
customer_id,
MAX(created) LastChargeDate
FROM
charges
GROUP BY
customer_id) maxCharges ON c.id = maxCharges.customer_id
LEFT JOIN
(SELECT
customer_id,
MAX(date) LastInvoiceDate
FROM
invoices
GROUP BY
customer_id) maxInvoices ON c.id = maxInvoices.customer_id
ORDER BY
c.created

Grouping by several variables in SAS

I want to sum up sales across agents, orders and the date. The following code runs, however, I just receive a duplicate of the total column instead of the sum. Any advice?
CODE:
(Select DISTINCT DATE, CUSTOMER, ORDERNR,
AREA, AGENT, Total, SUM(Total) AS TOTALSUM From data01 WHERE REPORT_DT between '2018-02-24' and '2018-02-25' GROUP BY DATE, CUSTOMER, ORDERNR,
AREA, AGENT, Total, ORDER BY AGENT)
Just a suggestion for clean your code that contain some error
You don't need distinct whe use GROUP BY and you have a wrong comma after the word Total in group by
(Select
DATE
, CUSTOMER
, ORDERNR
, AREA
, AGENT
, Total
, SUM(Total) AS TOTALSUM
From data01
WHERE REPORT_DT between '2018-02-24' and '2018-02-25'
GROUP BY DATE
, CUSTOMER
, ORDERNR
, AREA
, AGENT
, Total
ORDER BY AGENT)
Remove Total from the GROUP BY:
Select DATE, CUSTOMER, ORDERNR, AREA, AGENT, SUM(Total) AS TOTALSUM
From data01
where REPORT_DT between '2018-02-24' and '2018-02-25'
group by DATE, CUSTOMER, ORDERNR, AREA, AGENT;

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

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.

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