从一个表中选择,并从另外两个表中进行计数

Posted

技术标签:

【中文标题】从一个表中选择,并从另外两个表中进行计数【英文标题】:Select from one table with count from two other tables 【发布时间】:2016-02-26 19:50:25 【问题描述】:

我正在做一个查询,我从一个名为employee 的表中选择所有内容,并希望从另外两个表中计算employee_id,并在2 个单独的列中表示计数。

表格:

    员工[身份证等] 报告 [id、employee_id 等] office_report[id、employee_id 等]

到目前为止我所做的是:

SELECT emp.*, COUNT(rep.id ) no_of_field_reports, COUNT(of_rep.id) no_of_office_reports 
FROM employee emp
LEFT JOIN report rep
    ON (emp.id = rep.employee_id) 
LEFT JOIN office_report of_rep 
    ON (emp.id = of_rep.employee_id) 
WHERE emp.user_id =7 AND emp.active = 1 
GROUP BY emp.id, emp.name 
ORDER BY emp.name ASC

问题是,一旦我在两个报告表中都有报告,计数就会混乱。假设我在 report table 中有 16 个报告,在 office_report 表中有 2 个报告,no_of_field_reportsno_of_office_reports 的计数将变为32.

我显然遗漏了一些东西,但由于我不是 SQL 天才,我不知道是什么。

请务必解释导致问题的原因,以便我能够从错误中吸取教训并更好地理解这些类型的查询,因为这不会是最后一次。

我猜对于 mariaDB、mysql 和 SQL 来说,答案通常是相同的,所以我添加了所有这些标签以引起注意..

【问题讨论】:

几个选项。使用每个表的唯一 ID 的不同计数或将计数作为内联视图。计数混乱的原因是表之间的基数夸大了计数。 @xQbert 将 DISTINCT 添加到我的 SELECT 似乎不起作用..我想我做错了.. 【参考方案1】:

如果您追求不同的计数,可能是一种方法(尽管您可能需要调整到 PK 字段)

SELECT emp.*, 
       COUNT(distinct rep.id ) no_of_field_reports, --may need to be on Unique key instead
       COUNT(distinct of_rep.id) no_of_office_reports --may need to be on Unique key instead)
FROM employee emp
LEFT JOIN report rep
    ON (emp.id = rep.employee_id) 
LEFT JOIN office_report of_rep 
    ON (emp.id = of_rep.employee_id) 
WHERE emp.user_id =7 AND emp.active = 1 
GROUP BY emp.id, emp.name 
ORDER BY emp.name ASC

如果您不追求独特的计数,那么在连接之前获取计数的方法可能是正确的方法并且提供了灵活性。

SELECT emp.*, rep.cnt, of_Rep.cnt 
FROM employee emp
LEFT JOIN (SELECT count(ID) cnt , employee_ID
           FROM REPORT 
           GROUP BY employee_ID) rep
  ON (emp.id = rep.employee_id) 
LEFT JOIN (SELECT count(ID) cnt, Employee_ID      
          FROM office_report 
          GROUP BY employee_ID) of_rep 
  ON (emp.id = of_Rep.employee_id) 
WHERE emp.user_id =7 AND emp.active = 1 
GROUP BY emp.id, emp.name 
ORDER BY emp.name ASC

或使用相关查询(但并非一直支持,例如从该 SQL 创建物化视图时)

SELECT emp.*, 
      (SELECT count(ID)
       FROM REPORT 
       WHERE  emp.id = rep.employee_id) Report_Cnt, 
      (SELECT count(ID)
       FROM office_report  of_REP
       WHERE emp.id = of_Rep.employee_id) of_Rep_Cnt
FROM employee emp
WHERE emp.user_id =7 AND emp.active = 1 
GROUP BY emp.id, emp.name 
ORDER BY emp.name ASC

【讨论】:

不错..但为什么我需要调整PK? 我不知道 ID 是唯一的还是 PK 的......我说你可能需要调整。因为他们是PK的,所以你应该没问题。 报告ID也是唯一的..所以不需要调整吧? 如果 report.id 和 office-Report.id 是 pks,那么使用 count(distinct ID) 的第一个解决方案应该可以工作。

以上是关于从一个表中选择,并从另外两个表中进行计数的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 从一个表中选择,同时在另外两个表之间进行内部连接(多对多表和另一个表)

从两个表中选择和计数

连接两个表并从第一个表中选择一个相关值

从连接表中选择计数

从每个表中选择平均值

使用联合第 2 部分从多个表中选择计数相关行