Reputation: 1149
I had a question about a sql query on the website http://www.sql-ex.ru/. The query asks for :
Define the average price of the PCs and laptops produced by maker A.
The database schema is as follows:
Product(maker, model, type)
PC(code, model, speed, ram, hd, cd, price)
Laptop(code, model, speed, ram, hd, screen, price)
Printer(code, model, color, type, price)
I wrote my query as:
SELECT AVG(t.k) AS Avg_Price
FROM
(SELECT AVG(A.price) AS k
FROM PC A
JOIN Product B ON(A.model=B.model)
WHERE B.maker='A'
UNION ALL
SELECT AVG(C.price) AS k
FROM Laptop C
JOIN PRODUCT D ON(C.model=D.model)
WHERE D.maker='A') AS t
The problem is that it does not return the correct answer. The average returned is much higher than expected. Is the way the average is calculated wrong? How do I change the query so that it returns the expected answer? Any help would be appreciated.
Thanks
Upvotes: 2
Views: 4949
Reputation: 1
select avg(P.price) from
(select pc.model as model,pc.price as price from PC pc
union all
select L.model as model,L.price as price from Laptop L ) P
where P.model in
( select model from Product where maker = 'A' )
Upvotes: 0
Reputation: 321
I always have great struggle with JOINS(personally), so try this solution without joins. using IN Operator
with cte as (
SELECT price, model, code
FROM pc
WHERE model
IN (SELECT model FROM product WHERE maker = 'A')
UNION
SELECT price, model, code
FROM laptop
WHERE model
IN (SELECT model FROM product WHERE maker = 'A')
)
SELECT AVG(price) FROM cte
Upvotes: 0
Reputation: 9
It also work
SELECT Avg(price) AS avg_price
FROM (SELECT pc.price
FROM pc
INNER JOIN product
ON pc.model = product.model
WHERE maker = 'A'
UNION ALL
SELECT laptop.price
FROM laptop
INNER JOIN product
ON laptop.model = product.model
WHERE maker = 'A') Any_name
Upvotes: 1
Reputation: 1
select avg(price) as avg_price from
(select price
from Product, PC
where Product.model = PC.model
and maker = 'A'
union all
select price
from Product, Laptop
where Product.model = Laptop.model
and maker='A') avg_price
Upvotes: -1
Reputation: 9
Select avg(price) from
((select price,model from pc
union all
select price,model from laptop) a inner join product on product.model=a.model and product.maker='A' )
Firstly, I think that it would be better if I union
price
and model
of both tables and afterwards we can find average(price)
from maker A.
Upvotes: 0
Reputation: 28
SELECT AVG(price) FROM
(
SELECT PC.price, Product.maker FROM PC JOIN Product ON(PC.model=Product.model)
UNION ALL
SELECT Laptop.price, Product.maker FROM Laptop JOIN Product ON (Laptop.model = Product.model)
) T
GROUP BY T.maker HAVING T.maker = 'A'
It works because at first you select all laptop and pc prices, next you choose only records where maker = 'A', and the last step is counting an avg price.
Upvotes: 0
Reputation: 6414
with t1 as
(SELECT price, type from pc left join product on product.model = pc.model where maker = 'A'
UNION ALL
SELECT price, type from laptop left join product on product.model = laptop.model where maker = 'A')
select avg(price) from t1
Upvotes: 1
Reputation: 73
SELECT AVG(datatable.price) FROM
(
(SELECT PC.Price FROM PC INNER JOIN Product p1 ON PC.model=P1.model
WHERE P1.maker='A')
UNION ALL
(SELECT Laptop.price FROM Laptop INNER JOIN Product p2 ON
Laptop.model=P2.model WHERE P2.maker='A')
) datatable
Right.
The result of Your query:
Avg_Price
754.1666
Upvotes: 3
Reputation: 1
select AVG(P.price) as avg_price
from
(
select price, model from PC
UNION ALL
select price, model from Laptop
) P
join Product ON P.model = Product.model
where maker = 'A'
Upvotes: 0
Reputation: 263803
SELECT AVG(resultList.Price)
FROM
(
SELECT a.Price
FROM PC a INNER JOIN Product B
on a.Model = B.Model
WHERE B.Maker = 'A'
UNION ALL
SELECT c.Price
FROM Laptop c INNER JOIN Product d
on c.Model = d.Model
WHERE d.Maker = 'A'
) resultList
Upvotes: 0
Reputation: 16543
You're averaging pc prices and laptop prices separately, then averaging the averages together. Your query was good except that you shouldn't have averaged the prices in the sub queries. simply return the prices in the sub queries and average at the top level:
select
AVG( Price ) Avg_Price
from
(
(
select
pc.Price
from
PC pc
join Produt prod
on pc.Model = prod.Model
where
prod.Maker = 'A'
)
union all
(
select
pc.Price
from
Laptop l
join Produt prod
on l.Model = prod.Model
where
prod.Maker = 'A'
)
) q
Upvotes: 4
Reputation:
Your query is wrong. It is typically like how you to aggregation on distributed system. You can do aggregation on distributed node, then bring back the aggregation data and do agg on top of you return data, only except for the aggregation is transferable. AVG is not transerable. (1+2+3+4+5)/5 <> ((1+2)/2 + (1+2+3)/3)
Upvotes: 2