【问题标题】:Query shows values from tables differently [duplicate]查询以不同方式显示表中的值[重复]
【发布时间】:2020-10-06 15:31:54
【问题描述】:

我有 3 个表(出勤、津贴和扣除),其中有一些记录在出勤。工资、津贴。金额、扣除。金额列。我想用选定的日期对这些列中的值进行“求和”。

汇总的值必须是

  • 出勤率。工资:100
  • 津贴。金额:150
  • 扣减金额:120

但与我的查询值有很大不同。

SELECT Name, SUM(attendance.Wage), SUM(allowances.Amount), SUM(deductions.Amount) FROM employees
INNER JOIN attendance USING (EmployeeID)
INNER JOIN allowances USING (EmployeeID)
INNER JOIN deductions USING (EmployeeID)
WHERE MONTH(attendance.Date) = 6 AND YEAR(attendance.Date) = 2020 
AND
MONTH(allowances.Date) = 6 AND YEAR(allowances.Date) = 2020 
AND
MONTH(deductions.Date) = 6 AND YEAR(deductions.Date) = 2020 
GROUP BY employees.EmployeeID;

查询的输出:

  • 出勤率。工资:400
  • 津贴。金额:900
  • 扣除金额:720

为什么值会增加或增加?我该如何解决?

【问题讨论】:

  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。

标签: mysql sql join select sum


【解决方案1】:

因为您从每个表中获取多行并且join 将它们相乘。

如果没有其他信息,我会推荐相关子查询:

SELECT e.Name,
       (SELECT SUM(a.Wage)
        FROM attendance a
        WHERE a.EmployeeID = e.EmployeeID AND
              a.date >= '2020-06-01' AND a.date < '2020-07-01'
       ),
       (SELECT SUM(a.Amount)
        FROM allowances a
        WHERE a.EmployeeID = e.EmployeeID AND
              a.date >= '2020-06-01' AND a.date < '2020-07-01'
       ),
       (SELECT SUM(d.Amount)
        FROM deduction d
        WHERE d.EmployeeID = e.EmployeeID AND
              d.date >= '2020-06-01' AND d.date < '2020-07-01'
       )
FROM employees e;

在三个表中的每个表中都有一个(EmployeeId, date, amount/wage) 索引,这也应该比使用显式聚合和连接的替代方案具有更好的性能。

【讨论】:

  • 谢谢。现在我意识到了。但我不明白为什么这比使用显式聚合和连接的替代方案具有更好的性能? (这个我也不想学)
  • @user13758994 。 . .用索引中的查找替换外部聚合是性能可能会更好的原因。唯一的例外是,如果您有一个非常大的 employees 表,并且其中大多数在这些月份的任何表中都没有记录。
【解决方案2】:

您需要在子查询中下推聚合,否则总和会多次计算每个值。

SELECT e.Name, ad.total_attendance, aw.total_allowances, dd.total_deductions
FROM employees e
INNER JOIN (
    SELECT EmployeeID, SUM(wage) total_attendance
    FROM attendance 
    WHERE date >= '2020-06-01' and date < '2020-07-01'
    GROUP BY EmployeeID
) ad USING (EmployeeID)
INNER JOIN (
    SELECT EmployeeID, SUM(amount) total_allowances
    FROM allowances 
    WHERE date >= '2020-06-01' and date < '2020-07-01'
    GROUP BY EmployeeID
) aw USING (EmployeeID)
INNER JOIN (
    SELECT EmployeeID, SUM(amount) total_deductions
    FROM deductions 
    WHERE date >= '2020-06-01' and date < '2020-07-01'
    GROUP BY EmployeeID
) dd USING (EmployeeID)

【讨论】:

  • 谢谢。这也是工作。但在“e.Name”中,e 没有定义,只是有点错过。所有其他人都工作。
  • @user13758994:已修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 2021-02-06
  • 1970-01-01
相关资源
最近更新 更多