MySQL INNER JOIN из 3 таблиц с количеством и итогами - PullRequest
1 голос
/ 19 марта 2012

У меня настроен следующий пример базы данных -

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 ]

2 голосов
/ 19 марта 2012

Поскольку заказы связаны с компаниями через клиентов, я не думаю, что вам нужно выполнять два отдельных подзапроса и присоединяться к ним;скорее, я думаю, что вы можете просто написать:

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, то он обязательно принадлежит и к Acme Widget Company и к Intrepid Inc..Я не думаю, что это может быть правильно.Вместо поля customer_id, я думаю, orders должно иметь поле companies_customers_id.

0 голосов
/ 06 сентября 2017

У меня есть 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

Образец положен, нажмите здесь JPG
Дизайнер таблиц JPG

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...