2014-01-06 35 views
4

在查询中,我从三个表中获取数据:company,classes_by_companyperson。我在名称为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_idid?它们中的一个不应该足够吗?无论如何,你的问题是由于联合的倍增性质 - 也就是说,如果一个公司有两名雇员,并且有两个班级,那么最后会有四行 - 每个组合有一个(人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'作为唯一的公司ID,但是因为它存储它不一定按数字顺序。 – techAddict82

+1

忽略自动生成的id列中的“数字顺序” - 作为标准的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 

的条目根据你更新的问题:你只有n eed 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问题](http://stackoverflow.com/questions/7594865/why-没有MySQL的加-A-特征是 - 冲突 - 与-SQL标准)。如果你将会在不同的SQL平台上工作,你将会有不好的习惯。 – Kermit