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 SmithAcme 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_roundscore_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 个表的计数和总数的主要内容,如果未能解决你的问题,请参考以下文章

MySql INNER JOIN三表联查性能如何提升

26.MySQL中的内连接INNER JOIN

SQL中inner join,outer join和cross join的区别

由 INNER JOIN-ing 3 个表产生的记录集不可更新

SQL INNER JOIN 问题

mysql中inner join和outer join有啥区别?