【问题标题】:SQL SUM on 'generated' column“生成”列上的 SQL SUM
【发布时间】:2014-05-09 13:41:14
【问题描述】:

我的任务是统计每位员工的总缺勤天数。

我写了以下查询

SELECT name
    ,surname
    ,absentdays
FROM (
    SELECT name
        ,surname
        ,DATEDIFF("d", fromdate, todate) AS absentdays
    FROM DiseaseReport D
        , Employees E
    WHERE E.number = D.empnumber
    )

虽然这个查询工作得很好,但它并没有给我每个员工的“总”缺勤天数。相反,我会为每位员工获得更多行(如果适用)。

我尝试应用 SUM(absentdays) 或 GROUP BY 'name',但我猜这些不是选项,因为生成了 'absentdays' 列。

你们能给我这个“挑战”的替代解决方案吗?

【问题讨论】:

  • 与问题无关,但您应该考虑switching to the ANSI 92 Explicit JOIN syntax,您使用的 ANSI 89 语法(顾名思义)已经过时了 20 多年。
  • 如果这个查询“工作正常”,你必须使用 MySQL 以外的数据库,因为 MySQL DATEDIFF 函数需要两个参数(不是三个),并且必须为派生表分配别名。
  • 好吧,我想当时情况肯定发生了变化,因为我使用的是 Access 2013,它工作得很好。
  • 我认为 MySQL 没有任何改变。您的问题没有提到“Access 2013”​​作为 RDBMS。您的问题中对 RDBMS 的唯一引用是“mysql”标签,它指的是 MySQL,而不是 Access 2013。参考:http://stackoverflow.com/tags/mysql/info

标签: mysql sql select sum


【解决方案1】:

将函数(在您的情况下为sum)应用于“生成”列没有任何问题:

SELECT   name,
         surname,
         SUM(absentdays) AS total_absent_days
FROM     (SELECT name, 
                 surname,
                 DATEDIFF("d", fromdate, todate) AS absentdays
          FROM   DiseaseReport D, Employees E
          WHERE  E.number = D.empnumber
         )
GROUP BY name, surname

【讨论】:

    【解决方案2】:
    SELECT CONCAT(name,' ',surname) as fullName, sum(DATEDIFF("d", fromdate, todate)) as totalAbsendDays
    FROM DiseaseReport D, Employees E
    WHERE E.number = D.empnumber
    GROUP BY fullName
    

    【讨论】:

      【解决方案3】:

      生成它的事实并不重要。只需确保外部选择中的每一列都在 group by 子句中或使用聚合函数(在本例中为 SUM)

      SELECT name
          ,surname
          ,SUM(absentdays) 
      FROM (
          SELECT name
              ,surname
               ,DATEDIFF("d", fromdate, todate) AS absentdays
          FROM DiseaseReport D
              , Employees E
          WHERE E.number = D.empnumber
          )
      GROUP BY name, surname
      

      【讨论】:

        【解决方案4】:

        当你可以只使用你的内部选择时,为什么还要有一个冗余的选择语句?

        只删除除

        之外的所有内容
        SELECT name
            ,surname
            ,DATEDIFF("d", fromdate, todate) AS absentdays
        FROM DiseaseReport D
            , Employees E
        WHERE E.number = D.empnumber ;
        

        【讨论】:

        • 这行不通。他得到了重复的行,因为 DiseaseReport 表中每个员工有很多行。
        【解决方案5】:

        已经有很多答案了。从 MySQL 数据库中获取指定结果的最佳查询(因为已标记问题)是这样的:

        SELECT e.name
             , e.surname
             , SUM(DATEDIFF(d.todate,d.fromdate)) AS total_absentdays
          FROM Employees e
          JOIN DiseaseReport d
            ON d.empnumber = e.number
         GROUP BY e.surname, e.name
        

        这将只返回来自雇员的行,这些行在 DiseaseReport 表中至少有一行。如果您还想包括缺勤为零的员工,请在 JOIN 之前添加关键字 LEFT 以使其成为外连接操作,并返回零代替 NULL,将 total_absentdays 表达式包装在 IFNULL( expr, 0) 中.

        这个基本查询可以在 MySQL 以外的数据库(例如 Oracle 和 SQL Server)中工作,但导出“天数差异”的表达式除外,即 MySQL DATEDIFF() 函数需要替换为适合每个数据库的语法。

        为了从 SQL Server 获得等效结果,DATEDIFF 函数采用三个参数,其中较早的日期在较晚的日期之前,以获得非负值:

        SELECT e.name
             , e.surname
             , SUM(DATEDIFF('DAY',d.fromdate,d.todate)) AS total_absentdays
          FROM Employees e
          JOIN DiseaseReport d
            ON d.empnumber = e.number
         GROUP BY e.surname, e.name
         ORDER BY e.surname, e.name
        

        注意事项:

        不需要内联视图来获得指定的结果。

        放弃连接操作的老式逗号语法,改用 JOIN 关键字,并将连接谓词重新定位到 ON 子句。

        MySQL DATEDIFF() 函数接受两个参数,并返回两个日期值之间的整数天数。要让函数返回一个非负整数值,“较晚”日期应该是第一个参数,“较早”日期应该是第二个参数。

        此外,最佳做法是使用分配给表的别名来完全限定所有列引用。这使读者更容易阅读和破译 SQL ......例如读者不知道“姓名”列是来自疾病报告还是员工。

        对于 MySQL,GROUP BY 子句意味着 ORDER BY 子句。如果您希望结果以不同的顺序排列,请添加 ORDER BY 子句。

        【讨论】:

        • 如果我在 Access 2013 中尝试您的第一个示例,我会收到消息“组件 FROM 包含语法错误”
        • @John Dane:关系数据库在接受的语法上有所不同。我发布了对 MySQL 有效的语法,因为您的问题标有“mysql”标签,是对 MySQL 的引用,而不是 Access 2013。参考:http://stackoverflow.com/tags/mysql/info.
        【解决方案6】:

        很可能有多个同名+姓氏的员工, 所以使用 e.number 来区分:

        SELECT e.surname
            ,e.name
            ,e.number
            ,SUM(DATEDIFF("d", d.fromdate, d.todate)) AS _sickdays 
        FROM Employees     AS e
        JOIN DiseaseReport AS d ON d.empnumber = e.number
        GROUP BY number
        ORDER BY surname, name, number
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-26
          • 1970-01-01
          • 1970-01-01
          • 2013-03-16
          • 1970-01-01
          相关资源
          最近更新 更多