2013-09-27 90 views
2

我有一个“有很多”关系的一套MySQL的三个表:交易,订单和优惠券。Mysql的嵌套左加入与计数

Deals 
|----|--------------| 
| id | title  | 
|----|--------------| 
| 1 | Some deal | 
| 2 | Another deal | 
|----|--------------| 

Orders 
|----|---------|-----------| 
| id | deal_id | state | 
|----|---------|-----------| 
| 1 |  1 | purchased | 
| 2 |  1 | purchased | 
| 3 |  1 | expired | 
| 4 |  2 | purchased | 
|----|---------|-----------| 

Coupons 
|----|----------| 
| id | order_id | 
|----|----------| 
| 1 |  1 | 
| 2 |  1 | 
| 3 |  1 | 
| 4 |  2 | 
| 5 |  2 | 
| 6 |  4 | 
|----|----------| 

因此,交易有许多订单,其中有许多优惠券。

我希望做的是对的交易表中选择,而购买计数订单和优惠券的数量。

我知道如何让一个计数付费订单已经:

SELECT deals.*, count(orders.id) AS orders_purchased_count FROM deals 
LEFT JOIN orders ON deals.id=orders.deal_id AND orders.state='purchased' 
WHERE deal_id < 3 
GROUP BY deals.id 

Deals 
|----|--------------|------------------------| 
| id | title  | orders_purchased_count | 
|----|--------------|------------------------| 
| 1 | Some deal |      2 | 
| 2 | Another deal |      1 | 
|----|--------------|------------------------| 

同样,我可以得到订单的优惠券数量:

SELECT orders.*, count(coupons.id) AS coupons_count FROM orders 
LEFT JOIN coupons ON orders.id=couoons.orders_id 
WHERE orders.state='purchased' 
GROUP BY orders.id 

Orders 
|----|-----------|---------------| 
| id | state | coupons_count | 
|----|-----------|---------------| 
| 1 | purchased |    3 | 
| 2 | purchased |    2 | 
| 4 | purchased |    1 | 
|----|-----------|---------------| 

我的问题是:我如何结合这些,以便我可以在orders_purchased_count旁边添加coupons_count?

Deals 
|----|--------------|------------------------|---------------| 
| id | title  | orders_purchased_count | coupons_count | 
|----|--------------|------------------------|---------------| 
| 1 | Some deal |      2 |    5 | 
| 2 | Another deal |      1 |    1 | 
|----|--------------|------------------------|---------------| 

的棘手的事情,在我的情况,将是deals选择之前,我参加在ordersorders选择之前,我对coupons加入何时运行WHERE orders.state='purchased'过滤器时运行WHERE deal_id < 3过滤器。这是一个大的数据集,我不希望我的所有orderscoupons加载到内存中用于连接的目的。

在如何做到这一点的损失。

+0

是否有sqlfiddle? – Strawberry

回答

3

工作的呢?我无法理解你的担忧,哪一部分会变得棘手。

SELECT deals.*, COUNT(DISTINCT(orders.id)) AS orders_purchased_count, COUNT(coupons.id) AS coupons_count 
FROM deals 
LEFT JOIN orders 
    ON deals.id=orders.deal_id 
    AND orders.state='purchased' 
LEFT JOIN coupons 
    ON orders.id=coupons.orders_id 
WHERE deal_id < 3 
GROUP BY deals.id; 
+0

他可能正在努力挣扎的“棘手”部分是让购买的订单计数正确。这就是为什么'count'中的'distinct'的原因。 http://sqlfiddle.com/#!2/af049/26 –

+0

完美的是,它产生的正确,它在我的数据集上运行得很快。我担心我不得不在订单/优惠券上使用子查询,并且不希望在筛选交易之前加载它们。只使用连接可以避免这个问题。 – Devin

0

试试这个与共相关子查询,并加入

SELECT deals.*, count(orders.id) AS orders_purchased_count 
(
SELECT count(id) FROM coupons WHERE orders_id = orders.id 

) AS coupons_count 

FROM deals 
LEFT JOIN orders ON deals.id=orders.deal_id AND orders.state='purchased' 
WHERE deal_id < 3 
GROUP BY deals.id