在查询中,我从三个表中获取数据: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)
);
答案 0 :(得分:2)
我不得不问 - 为什么company
同时拥有company_id
和 id
?其中一个不应该足够吗?无论如何,你的问题是由于连接的乘法性质 - 也就是说,如果公司有2名员工,2个班级,你最终会得到4行 - 每个组合1个(A + A级,人A + B级,B + A级,B + B级)。因此,这是通常解决问题的另一种方式:
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
(以及resulting fiddle - 感谢您提供一个!)
请注意,虽然两个答案都给出了正确的结果,但这个版本的性能可能更高,因为它有更高的机会使用索引。
答案 1 :(得分: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)
,因为您正在尝试计算课程,而不是公司。