MySQL包含计数和总计的3个表的内部联接

MySQL包含计数和总计的3个表的内部联接,mysql,sql,Mysql,Sql,我已经建立了以下示例数据库- CREATE TABLE IF NOT EXISTS `companies`( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `company` varchar(75) NOT NULL, PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; INSERT INTO `companies` (`id`, `

我已经建立了以下示例数据库-

CREATE TABLE IF NOT EXISTS `companies`( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `company` varchar(75) NOT NULL, PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; INSERT INTO `companies` (`id`, `company`) VALUES (1, 'Acme Widget Company'), (2, 'Intrepid Inc.'), (3, 'Allied Corp.'); CREATE TABLE IF NOT EXISTS `companies_customers` ( `id` int(11) NOT NULL AUTO_INCREMENT, `company_id` int(11) NOT NULL, `customer_id` int(11) NOT NULL, PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; INSERT INTO `companies_customers` (`id`, `company_id`, `customer_id`) VALUES (1, 2, 1), (2, 2, 2), (3, 2, 4), (4, 1, 3), (5, 1, 1); CREATE TABLE IF NOT EXISTS `customers` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `firstname` varchar(25) NOT NULL, `lastname` varchar(50) NOT NULL, PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ; INSERT INTO `customers` (`id`, `firstname`, `lastname`) VALUES (1, 'John', 'Smith'), (2, 'Sue', 'Jones'), (3, 'David', 'Flanders'), (4, 'Kathy', 'Freeman'); CREATE TABLE IF NOT EXISTS `orders` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `customer_id` int(11) NOT NULL, `amount` decimal(10,0) NOT NULL, PRIMARY KEY (`id`) )ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ; INSERT INTO `orders` (`id`, `customer_id`, `amount`) VALUES (1, 1, 500), (2, 3, 1000), (3, 1, 250), (4, 4, 800), (5, 4, 100); 我需要编写一个查询,检索所有公司名称的列表、每个公司的客户数量计数以及每个公司的客户订单总数,如下所示-

Company Total Customers All Orders Total Acme Widget Company 2 750 Intrepid Inc. 3 1650 Allied Corp. 0 0 我几乎用以下SQL解决了它-

SELECT company AS 'Company', customersCount AS 'Total Customers', customerOrdersTotal AS 'All Orders Total' FROM ( SELECT cc.customer_id, SUM(innerQuery.ordersTotal) customerOrdersTotal FROM (SELECT cu.id customerId, SUM(amount) ordersTotal FROM customers cu JOIN orders o ON o.customer_id = cu.id GROUP BY customerId ) innerQuery JOIN companies_customers cc ON innerQuery.customerId = cc.customer_id GROUP BY cc.customer_id ) inner_1 RIGHT JOIN ( SELECT cc.id, c.company, COUNT(*) customersCount FROM companies c JOIN companies_customers cc ON c.id = cc.company_id GROUP BY c.id ) inner_2 ON inner_1.customer_id = inner_2.id
它不会打印出没有客户或总数的公司。如此接近,我只需要朝正确的方向轻推一下。谢谢。

由于订单通过客户链接到公司,我认为您不需要执行两个单独的子查询并加入它们;相反,我认为你可以写:

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.的客户——但订单只是客户的财产,而不是公司的财产。这意味着,如果订单属于约翰·史密斯,那么它必然同时属于Acme Widget Company和Intrepid Inc。。我认为那是不对的。我认为orders需要一个公司客户id字段,而不是客户id字段。

我有3个表格,用于保存团队、锦标赛和得分团队成员,关于竞争团队a和团队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

我需要的是每家公司的“金额”列的总数,而不是订单数量。所以,我认为剧照需要一个子集?您的解决方案导致所有订单总数为9 3+5+1。这是不正确的,因为orders表中只有5行。是的,我同意订单需要一个companys\u customers\u id字段。因此,我对您的SQL进行了修改-很抱歉格式不好-似乎不知道如何在这些回复中应用标记。Re:amount列的总计:Duh,抱歉,这应该是显而易见的。我已将答案中的查询更新为使用IFNULLSUMorders.amount,0而不是COUNT1。Re::注释中不支持该选项。您可以通过使用反勾号获得单间距文本,`,但这不会保留额外的空格、换行符等。