我开始拼凑在一起之前写几个子查询。我个人的建议是在整个解决方案之前总是将问题分解成更小的一部分。
例如,我需要知道的一件事是每个客户都没有购买的所有产品。我这样做是由已经在顺序表中存在的交叉连接的客户和产品表(让所有配对),除去对,是这样的:
-- Get all customer/product pairings where customer_product
-- does not exist in orders table
SELECT c.id, p.id
FROM customer c
CROSS JOIN product p
WHERE (c.id, p.id) NOT IN (SELECT * FROM orders)
ORDER BY c.id;
我也写了一个子查询,以获得平均收视率每个产品。这个查询将返回NULL,如果产品没有等级:
SELECT p.id, AVG(r.rate) AS averageRating
FROM product p
LEFT JOIN rate r ON r.product_id = p.id
GROUP BY p.id;
现在,我可以包括这两个子查询和选择客户ID,产品ID,和他们没有购买每个产品的评价:
SELECT t1.customerID, t1.productID, t2.averageRating
FROM(
SELECT c.id AS customerID, p.id AS productID
FROM customer c
CROSS JOIN product p
WHERE (c.id, p.id) NOT IN (SELECT * FROM orders)
ORDER BY c.id) t1
JOIN(
SELECT p.id AS productID, AVG(r.rate) AS averageRating
FROM product p
LEFT JOIN rate r ON r.product_id = p.id
GROUP BY p.id) t2 ON t2.productID = t1.productID;
这是最难的部分。剩下的唯一要做的事就是进行一些聚合,以便从每个客户没有购买的商品中获得最大的评分,然后在上面的查询中加入聚合查询,条件是最高评分与平均评分相匹配。所以,这里是我已经把滔天查询:
SELECT t1.customerID, t1.productID, t1.averageRating
FROM(
SELECT t1.customerID, t1.productID, t2.averageRating
FROM(
SELECT c.id AS customerID, p.id AS productID
FROM customer c
CROSS JOIN product p
WHERE (c.id, p.id) NOT IN (SELECT * FROM orders)
ORDER BY c.id) t1
JOIN(
SELECT p.id AS productID, AVG(r.rate) AS averageRating
FROM product p
LEFT JOIN rate r ON r.product_id = p.id
GROUP BY p.id) t2 ON t2.productID = t1.productID) t1
JOIN(
SELECT t1.customerID, MAX(t2.averageRating) AS maxRating
FROM(
SELECT c.id AS customerID, p.id AS productID
FROM customer c
CROSS JOIN product p
WHERE (c.id, p.id) NOT IN (SELECT * FROM orders)
ORDER BY c.id) t1
JOIN(
SELECT p.id AS productID, AVG(r.rate) AS averageRating
FROM product p
LEFT JOIN rate r ON r.product_id = p.id
GROUP BY p.id) t2 ON t2.productID = t1.productID
GROUP BY t1.customerID) t2 ON t2.customerID = t1.customerID AND t2.maxRating = t1.averageRating
ORDER BY t1.customerID;
这里是从MySQL工作台结果的快照:
要注意的重要一点是,我并没有消除领带。因此,例如,客户2没有购买产品1或2并且它们具有相同的评级,因此返回两行。
我在MySQL的测试,因为SQL小提琴是行不通的,但我得到了工作,所以这里是一个Fiddle例如,如果你喜欢的。
你想为所有客户的所有此类产品的列表,或只为特定的客户? – eggyal 2015-03-08 17:23:47
对于顾客还没有购买但评价过的所有产品。 – Dino 2015-03-08 17:24:38
您是否想要为所有客户提供所有此类产品的清单,还是只为特定客户提供? – eggyal 2015-03-08 17:25:37