Reputation: 1684
I have 3 tables:
shops
, PRIMARY KEY cid,zbid
shop_items
, PRIMARY KEY id
shop_inventory
, PRIMARY KEY id
shops a
is related to shop_items b
by the following: a.cid=b.cid AND a.zbid=b.szbid
shops
is not directly related to shop_inventory
shop_items b
is related to shop_inventory c
by the following: b.cid=c.cid AND b.id=c.iid
Now, I would like to run a query which returns a.*
(all columns from shops
). That would be:
SELECT a.* FROM shops a WHERE a.cid=1 AND a.zbid!=0
Note that the WHERE
clause is necessary.
Next, I want to return the number of items in each shop:
SELECT
a.*,
COUNT(b.id) items
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
As you can see, I have added a GROUP BY
clause for this to work.
Next, I want to return the average price of each item in the shop. This isn't too hard:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
My next criteria is where it gets complicated. I also want to return the unique buyers for each shop. This can be done by querying shop_inventory c
, getting the COUNT(DISTINCT c.zbid)
. Now remember how these tables are related; this should only be done for the rows in c
which relate to an item in b
which is owned by the respective shop, a
.
I tried doing the following:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price,
COUNT(DISTINCT c.zbid)
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
LEFT JOIN shop_inventory c ON c.cid=b.cid AND c.iid=b.id
WHERE a.cid=1
GROUP BY b.szbid,b.cid
However, this did not work as it messed up the items
value. What is the proper way to achieve this result?
I also want to be able to return the total number of purchases made in each shop. This would be done by looking at shop_inventory c
and adding up the c.quantity
value for each shop. How would I add that in as well?
Upvotes: 0
Views: 115
Reputation: 23125
Try this solution:
SELECT a.*,
COALESCE(b.item_cnt, 0) AS item_cnt,
COALESCE(b.avg_price, 0) AS avg_price,
COALESCE(b.buyer_cnt, 0) AS buyer_cnt
FROM shops a
LEFT JOIN (
SELECT a.cid,
a.szbid,
COUNT(*) AS item_cnt,
AVG(a.price) AS avg_price,
b.buyer_cnt
FROM shop_items a
LEFT JOIN (
SELECT cid,
iid,
COUNT(DISTINCT zbid) AS buyer_cnt
FROM shop_inventory
WHERE cid = 1
GROUP BY cid,
iid
) b ON a.cid = b.cid AND a.id = b.iid
WHERE a.cid = 1 AND
a.szbid <> 0
GROUP BY a.cid,
a.szbid
) b ON a.cid = b.cid AND a.zbid = b.szbid
WHERE a.cid = 1 AND
a.zbid <> 0
Upvotes: 2
Reputation: 14596
Instead of COUNT(DISTINCT c.zbid)
+ LEFT JOIN shop_inventory
you could write a subselect:
SELECT
a.*,
COUNT(b.id) items,
AVG(COALESCE(b.price,0)) average_price,
( SELECT COUNT(DISTINCT c.zbid)
FROM shop_inventory c
WHERE c.cid=b.cid AND c.iid=b.id
)
FROM shops a
LEFT JOIN shop_items b ON b.cid=a.cid AND b.szbid=a.zbid
WHERE a.cid=1
GROUP BY b.szbid,b.cid
Upvotes: 1