I'm trying to write a query to return all products with higher than average dollar sales. The relevant tables and columns are:
I can write the subquery that gets dollar sales for each product, but I'm having trouble applying the average function to that subquery. Everything I try returns a syntax error. Following is what I thought should be close to the answer:
select avg(sum) as avg_sales
from (
select sum(b.quantity * a.price) as total_sales
from products a, orderlines b
where a.prod_id = b.prod_id
group by a.prod_id
);
When I try this, I get:
ERROR: subquery in FROM must have an alias.
I don't get this, but I'm new to Postgres. Anyway, adding an alias gives me:
select avg(totals) as avg_sales
from (
select sum(b.quantity * a.price) as total_sales
from products a, orderlines b
where a.prod_id = b.prod_id group by a.prod_id
) as totals;
When I try this, I get: ERROR: function avg(record) does not exist
I realize the above code is just getting the overall average sales. If I can get average sales, then it should be easy to get the products that are above average.
When I try this, I get: ERROR: function avg(record) does not exist
This is because you are passing the alias of the derived table to the avg()
function, which means you are passing a complete row (=record) to it, not a single column (value).
To get that working you need to use:
select avg(totals.total_sales) as avg_sales
from (
select sum(ol.quantity * p.price) as total_sales
from products p
join orderlines ol on p.prod_id = ol.prod_id
group by p.prod_id
) as totals;
Note that I replaced the ancient, outdated and fragile implicit join with a modern explicit JOIN
operator. If you are learning SQL you should get used to that syntax.
To get the products with a higher then average sale, you need to calculate both: the sales per product and the average sale.
This can be achieved by using a window function while aggregating:
select p.prod_id,
sum(ol.quantity * p.price) as total_sales,
avg(sum(ol.quantity * p.price)) over () as average_sales
from products p
join orderlines ol on p.prod_id = ol.prod_id
group by p.prod_id;
This can now be wrapped in a derived table to filter out those with a lower total sales:
select *
from (
select p.prod_id,
sum(ol.quantity * p.price) as total_sales,
avg(sum(ol.quantity * p.price)) over () as average_sales
from products p
join orderlines ol on p.prod_id = ol.prod_id
group by p.prod_id
) t
where total_sales >= average_sales;
SQLFiddle example: http://sqlfiddle.com/#!15/7f8ab/1
You can try something like this. First using a sub query find the average sales, then get all the products above that sales
SELECT p.prod_id, o.quantity
FROM products p INNER JOIN orderlines o
ON p.prod_id = o.prod_id
WHERE o.quantity > ( SELECT AVG(ol.quantity)
FROM products pr INNER JOIN orderlines ol
ON pr.prod_id = ol.prod_id
)
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.