MySQL INNER JOIN 3 个表的计数和总数
Posted
技术标签:
【中文标题】MySQL INNER JOIN 3 个表的计数和总数【英文标题】:MySQL INNER JOIN of 3 tables with count and totals 【发布时间】:2012-04-04 01:45:44 【问题描述】:我设置了以下示例数据库 -
如果不存在“公司”,则创建表( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `company` varchar(75) NOT NULL, 主键(`id`) )ENGINE=InnoDB 默认字符集=latin1 AUTO_INCREMENT=3 ; 插入`companies`(`id`,`company`)值 (1, 'Acme Widget Company'), (2,“无畏公司”), (3,“联合公司”); 如果不存在“companies_customers”,则创建表( `id` int(11) NOT NULL AUTO_INCREMENT, `company_id` int(11) NOT NULL, `customer_id` int(11) NOT NULL, 主键(`id`) )ENGINE=InnoDB 默认字符集=latin1 AUTO_INCREMENT=6 ; 插入“companies_customers”(“id”、“company_id”、“customer_id”)值 (1, 2, 1), (2, 2, 2), (3, 2, 4), (4, 1, 3), (5, 1, 1); 如果不存在“客户”,则创建表( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `firstname` varchar(25) NOT NULL, `lastname` varchar(50) NOT NULL, 主键(`id`) )ENGINE=InnoDB 默认字符集=latin1 AUTO_INCREMENT=5 ; 插入`customers`(`id`、`firstname`、`lastname`)值 (1,“约翰”,“史密斯”), (2,“苏”,“琼斯”), (3,“大卫”,“佛兰德斯”), (4,“凯西”,“弗里曼”); 如果不存在“订单”,则创建表( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `customer_id` int(11) NOT NULL, `金额`小数(10,0)不为空, 主键(`id`) )ENGINE=InnoDB 默认字符集=latin1 AUTO_INCREMENT=6 ; 插入`订单`(`id`,`customer_id`,`amount`)值 (1, 1, 500), (2, 3, 1000), (3, 1, 250), (4, 4, 800), (5, 4, 100);我需要编写一个查询来检索所有公司名称的列表、每家公司的客户数量以及每家公司的客户订单总和,如下所示 -
公司 客户总数 所有订单总数 Acme Widget 公司 2 750 无畏公司 3 1650 联合公司 0 0我几乎用下面的 SQL 解决了它 -
SELECT company AS 'Company', customersCount AS 'Total Customers', customerOrdersTotal AS 'All Orders Total' 从 ( SELECT cc.customer_id, SUM(innerQuery.ordersTotal) customerOrdersTotal FROM (SELECT cu.id customerId, SUM(amount) ordersTotal 来自客户 加入订单 o ON o.customer_id = cu.id 按客户 ID 分组 ) 内部查询 加入公司_客户 cc ON innerQuery.customerId = cc.customer_id 按 cc.customer_id 分组 ) 内部_1 正确加入 ( SELECT cc.id, c.company, COUNT(*) customersCount 来自公司 c 加入公司_客户 cc ON c.id = cc.company_id 按 c.id 分组 ) 内部_2 ON inner_1.customer_id = inner_2.id它不会打印出没有客户或总数的公司(Allied)。如此接近,我只需要朝正确的方向轻推。谢谢。
【问题讨论】:
【参考方案1】:由于订单通过客户链接到公司,我认为您不需要执行两个单独的子查询并加入它们;相反,我认为你可以写:
SELECT companies.company AS "Company",
IFNULL(COUNT(DISTINCT companies_customers.customer_id), 0) AS "Total Customers",
IFNULL(SUM(orders.amount), 0) AS "All Orders Total"
FROM companies
LEFT
JOIN companies_customers
ON companies_customers.company_id = companies.id
LEFT
JOIN orders
ON orders.customer_id = companies_customers.customer_id
GROUP
BY companies.id
;
编辑添加:也就是说,我不得不说架构对我来说并没有什么意义。您在客户和公司之间存在多对多关系 - 例如,John Smith
是 Acme Widget Company
的客户 和 Intrepid Inc.
- 但订单只是客户,不是公司的。这意味着如果一个订单属于John Smith
,那么它必然both 属于Acme Widget Company
并且 属于Intrepid Inc.
。我不认为这是对的。我认为 orders
需要有一个 companies_customers_id
字段,而不是 customer_id
字段。
【讨论】:
我需要每家公司的“金额”列的总数,而不是所下订单的 COUNT(1) 个。所以,我认为 Stills 需要一个子选择?您的解决方案导致“所有订单总计”为 9 (3+5+1)。这是不正确的,因为订单表中只有 5 行。是的,我同意需要 company_customers_id 字段的订单。 所以,我想出了对您的 SQL 的修改 -SELECT Companies.company AS "Company", IFNULL(COUNT(DISTINCT Companies_customers.customer_id), 0) AS "Total Customers" , COUNT(1) AS "Total Orders Placed", SUM(orders.amount) AS 'Total Value of Orders' FROM Companies LEFT JOIN Companies_customers ON Companies_customers.company_id = Companies.id LEFT JOIN orders ON orders.customer_id = Companies_customers.customer_id GROUP BY company.id抱歉格式错误 - 似乎无法弄清楚如何使
标记适用于这些回复。回复:“金额”列的总数:呃,抱歉,这应该很明显。我已将答案中的查询更新为使用
IFNULL(SUM(orders.amount), 0)
而不是COUNT(1)
。 Re: : cmets 不支持。您可以使用反引号`
获得等宽文本,但这不会保留额外的空格和换行符等等。
【参考方案2】:
我有 3 张桌子要保留 team
,tournament_round
和 score_team_member
关于比赛 TEAM_A 与 TEAM_B 的比赛,多轮。(1,2,3...n)和多个团队成员自己打分。上面这段代码很有用。
SELECT team.name AS "TEAM",team.id,
IFNULL(COUNT(DISTINCT `tournament_round`.id), 0) AS "TotalWin",
IFNULL(SUM(`score_team_member`.`score`)/(select count(*) from `team_member`where team_id=team.id group by team_id ), 0) AS "ScoreofTeam"
FROM `team`
LEFT
JOIN `tournament_round`
ON `tournament_round`.team_winner_id = `team`.id
LEFT
JOIN `score_team_member`
ON `score_team_member`.team_id = `team`.id
WHERE `team`.thematch_id='6' AND `team`.`category1`='MEP'
GROUP BY `team`.id ORDER by `TotalWin`DESC ,`ScoreofTeam` DESC
Sample out put click here JPG Table Designer JPG
【讨论】:
以上是关于MySQL INNER JOIN 3 个表的计数和总数的主要内容,如果未能解决你的问题,请参考以下文章
SQL中inner join,outer join和cross join的区别