MySQL INNER JOIN共有3个表,包含计数和总计

时间:2012-03-19 14:58:43

标签: 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`, `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

没有客户或总计,它不会打印出公司(Allied)。如此接近,我只需要朝着正确的方向轻推。感谢。

2 个答案:

答案 0 :(得分:2)

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

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是[{1}} Acme Widget Company的客户 - 但是订单只是客户的财产,不是的公司。这意味着,如果订单属于Intrepid Inc.,那么它必须属于 John Smith Acme Widget Company。我认为这不对。我认为Intrepid Inc.不需要customer_id字段,而是需要orders字段。

答案 1 :(得分:0)

我有3个表格可以保持teamtournament_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