简单快速的问题,我有这些表:
//table people
| pe_id | pe_name |
| 1 | Foo |
| 2 | Bar |
//orders table
| ord_id | pe_id | ord_title |
| 1 | 1 | First order |
| 2 | 2 | Order two |
| 3 | 2 | Third order |
//items table
| item_id | ord_id | pe_id | title |
| 1 | 1 | 1 | Apple |
| 2 | 1 | 1 | Pear |
| 3 | 2 | 2 | Apple |
| 4 | 3 | 2 | Orange |
| 5 | 3 | 2 | Coke |
| 6 | 3 | 2 | Cake |
Run Code Online (Sandbox Code Playgroud)
我需要查询列出所有人,计算订单数量和项目总数,如下所示:
| pe_name | num_orders | num_items |
| Foo | 1 | 2 |
| Bar | 2 | 4 |
Run Code Online (Sandbox Code Playgroud)
但我不能让它发挥作用!我试过了
SELECT
people.pe_name,
COUNT(orders.ord_id) AS num_orders,
COUNT(items.item_id) AS num_items
FROM
people
INNER JOIN orders ON (orders.pe_id = people.pe_id)
INNER JOIN items ON items.pe_id = people.pe_id
GROUP BY
people.pe_id;
Run Code Online (Sandbox Code Playgroud)
但这会返回num_*不正确的值:
| name | num_orders | num_items |
| Foo | 2 | 2 |
| Bar | 8 | 8 |
Run Code Online (Sandbox Code Playgroud)
我注意到,如果我尝试加入一个表,它的工作原理:
SELECT
people.pe_name,
COUNT(orders.ord_id) AS num_orders
FROM
people
INNER JOIN orders ON (orders.pe_id = people.pe_id)
GROUP BY
people.pe_id;
//give me:
| pe_name | num_orders |
| Foo | 1 |
| Bar | 2 |
//and:
SELECT
people.pe_name,
COUNT(items.item_id) AS num_items
FROM
people
INNER JOIN items ON (items.pe_id = people.pe_id)
GROUP BY
people.pe_id;
//output:
| pe_name | num_items |
| Foo | 2 |
| Bar | 4 |
Run Code Online (Sandbox Code Playgroud)
如何将这两个查询合二为一?
Cyr*_*don 34
将项目与订单联系起来比与人们联系更有意义!
SELECT
people.pe_name,
COUNT(distinct orders.ord_id) AS num_orders,
COUNT(items.item_id) AS num_items
FROM
people
INNER JOIN orders ON orders.pe_id = people.pe_id
INNER JOIN items ON items.ord_id = orders.ord_id
GROUP BY
people.pe_id;
Run Code Online (Sandbox Code Playgroud)
与人民一起加入物品会引起很多疑惑.例如,3号蛋糕物品将通过人与人之间的联系与订单2相关联,您不希望这种情况发生!
所以:
1-您需要很好地理解您的架构.物品是订单的链接,而不是人.
2-您需要为一个人计算不同的订单,否则您将计算与订单一样多的商品.
正如弗兰克指出的那样,你需要使用DISTINCT.此外,由于您使用的是复合主键(完全没问题,BTW),因此您需要确保在连接中使用整个键:
SELECT
P.pe_name,
COUNT(DISTINCT O.ord_id) AS num_orders,
COUNT(I.item_id) AS num_items
FROM
People P
INNER JOIN Orders O ON
O.pe_id = P.pe_id
INNER JOIN Items I ON
I.ord_id = O.ord_id AND
I.pe_id = O.pe_id
GROUP BY
P.pe_name
Run Code Online (Sandbox Code Playgroud)
没有I.ord_id = O.ord_id,它将每个项目行连接到一个人的每个订单行.