2014-01-06 2 views
4

В запросе я получаю данные из трех таблиц: company, classes_by_company и person. У меня есть внешний ключ во всех таблицах с именем company_id. Я использую левое соединение для сетки таблиц с соответствующими company_id. Я пытаюсь выяснить количество классов для компании и сотрудников. Я получаю значения, которые не подходят для обоих. Вот SQIDDLEЗапрос с использованием счета с использованием внешнего ключа

SELECT a.id, 
a.company_id, 
a.status, 
COUNT(c.company_id) AS classes_per_company, 
COUNT(p.employee_id) AS employees_per_company 
FROM company a 
LEFT JOIN classes_by_company c 
ON a.company_id = c.company_id 
LEFT JOIN person p 
ON a.company_id = p.company_id 
GROUP BY a.company_id 

Структура таблицы:

CREATE TABLE company 
    (
    id int auto_increment primary key, 
    company_id int, 
    status varchar(20) 
    ); 
CREATE TABLE classes_by_company 
(
id int auto_increment primary key, 
company_id int, 
class_name varchar(20) 
); 
CREATE TABLE person 
(
id int auto_increment primary key, 
employee_id int, 
company_id int, 
person_name varchar(20) 
); 

enter image description here

+0

* «классы для компании и сотрудников» * .. можете ли вы показать нам желаемый результат? – Kermit

+0

@FreshPrinceOfSO о да! извините, я добавлю это сразу. – techAddict82

ответ

2

я должен спросить - почему company имеют как company_idиid? Разве один из них не должен быть достаточным? Независимо от этого, ваша проблема связана с мультипликативным характером объединений, то есть, если в компании есть 2 сотрудника и 2 класса, вы получаете 4 строки - 1 для каждой комбинации (человек A + класс A, человек A + класс B, человек B + класс A, человек B + класс B). В связи с этим, вот другой способ вопрос обычно решается: (! И resulting fiddle - спасибо за обеспечение одного)

SELECT a.id, a.company_id, a.status, 
     c.count AS classes_per_company, 
     p.count AS employees_per_company 
FROM company a 
LEFT JOIN (SELECT company_id, COUNT(*) as count 
      FROM classes_by_company 
      GROUP BY company_id) c 
     ON a.company_id = c.company_id 
LEFT JOIN (SELECT company_id, COUNT(*) as count 
      FROM person 
      GROUP BY company_id) p 
     ON a.company_id = p.company_id 

Обратите внимание, что, в то время как оба ответа дают правильный результат, эта версия скорее всего, будет более результативным, так как он имеет более высокий шанс использовать индексы.

+0

Теперь я понимаю. Ну, я использовал 'id' только для автоматического приращения и' company_id' как уникальный идентификатор компании, но поскольку он хранится, он не обязательно идет в числовом порядке. – techAddict82

+1

Игнорировать «числовой порядок» из столбцов с автогенерированными столбцами. SQL как стандарт по существу утверждает, что строки не имеют собственного порядка (это целая цель для «ORDER BY») - такие вещи, как индексы, являются оптимизациями. Это, вероятно, нарушает правило присвоения значения суррогатным ключам. Если вам нужно знать, что было первым, используйте столбец временной отметки (установленный в UTC). Обычно вам нужен только один внутренний ключ для таблицы, либо один столбец, либо составной ключ (например, для таблиц перекрестных ссылок - что происходит, если человек работает более чем для одной компании?). –

+0

Хорошая точка! Я рад, что знаю это сейчас. Я буду применять его. – techAddict82

1

я думаю, что вам нужно COUNT(DISTINCT c.company_id), поскольку данные имеют записи одного и того же company_id и класса

SELECT a.id, 
     a.company_id, 
     a.status, 
     COUNT(DISTINCT c.id) AS classes_per_company, 
     COUNT(DISTINCT p.employee_id) AS employees_per_company 
FROM company a 
LEFT JOIN classes_by_company c ON a.company_id = c.company_id 
LEFT JOIN person p ON a.company_id = p.company_id 
GROUP BY a.id,a.company_id,a.status 

в соответствии с вашим обновленным вопросом: вам нужно только COUNT(DISTINCT p.employee_id)

также я думаю, что вы должны COUNT(DISTINCT c.id) вместо COUNT(c.company_id), так как вы пытаетесь считать классы, а не компании.

+0

Стандартное утверждение ANSI было бы неплохо. – Kermit

+0

@FreshPrinceOfSO Что вы подразумеваете под этим? Я очень хочу знать. –

+0

Ваш ответ (по ошибке MySQL) не является стандартом ANSI, поскольку вы являетесь столбцами «SELECT», которые не находятся в вашей «GROUP BY». [Документация] (http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html) и [SO Question] (http://stackoverflow.com/questions/7594865/why- это-MySQL-добавить-а-функция, что-конфликты-с-SQL-стандартами). Если вы когда-нибудь будете работать на другой платформе SQL, у вас будут плохие привычки пинать. – Kermit

Смежные вопросы