mysql组返回不正确的结果

时间:2014-04-25 17:18:12

标签: php mysql sql group-by sum

我有两个表(时间表和任务),每个表包含一个小时值列“已分配小时数”和“实际小时数”,我试图获得这两个值的总和。 时间表表格包含“staff_id”的整数值,对应于任务表中的“assigned_to”

任务表包含:

task_id INT(11)
assigned_to INT(11)
date_start DATE
hrs DECIMAL (10,0)

时间表表包含:

timesheet_id (int)
name varchar(100)
hours decimal(10,0)
staff_id(INT 11)

我的查询如下:

    SELECT
        timesheet.staff_id,
        task.assigned_to,
        SUM(task.hrs) AS assigned_hrs,
        timesheet.name,
        SUM(timesheet.hours) AS actual_hours
    FROM timesheet
    INNER JOIN task
    ON timesheet.staff_id = task.assigned_to
    GROUP BY timesheet.name

将(错误地)导致:

staff_id       |assigned_to |assigned_hrs    | name.         |  actual_hours |
---------------|------------|----------------|---------------|---------------|
4              |4           | 1364           | John Smith    |52          
2              |2           | 80             | Jane Doe      |14.5        
6              |6           | 454            | Test User 1   |40          
9              |9           | 262            | Test User 2   |4           

以上是我想要的,但是 所有的结果都是正确的,但约翰史密斯的分配时间增加了一倍。 我知道这与“分组陷阱”有关 如下所述:

http://wikido.isoftdata.com/index.php/The_GROUPing_pitfall

但我只是试图弄明白这一点。 有人能指出我正确的方向吗?

(再次编辑)         如果我只在任务表上运行查询:

    SELECT
    task.assigned_to,
    SUM(task.hrs) AS allocated_hrs
    FROM task
    GROUP BY task.assigned_to

它(正确)导致:

assigned_to | allocated_hrs |
----------------------------
4           |    682
7           |    378
2           |    40
6           |    227
9           |    262

你可以看到约翰史密斯的用户ID“4”翻了一倍(也是ID 6)

仅在时间表表格上运行查询:

    SELECT
    timesheet.name,
    SUM(timesheet.hours) AS actual_hours
    FROM timesheet
    GROUP BY timesheet.name

正确导致:

    name    |  Actual_hrs
    -------------------------
    Jane Doe   | 19.5
    John Smith | 6.5
    Test User1 | 4
    Test User2 | 5

运行JoachimL提供的查询导致:

    staff_id |  assigned_to |   assigned_hrs |  name |  actual_hours
    ----------------------------------------------------------------------
    2   2   40  Jane Doe    19.5
    4   4   24  John Smith  6.5
    4   4   7   John Smith  6.5
    4   4   21  John Smith  6.5
    4   4   210 John Smith  6.5
    4   4   28  John Smith  6.5
    4   4   91  John Smith  6.5
    6   6   14  Test User 1 8
    6   6   91  Test User 1 8
    6   6   28  Test User 1 8
    6   6   3   Test User 1 8
    9   9   24  Test User 2 1
    9   9   91  Test User 2 1
    9   9   56  Test User 2 1

这是一个小提琴http://sqlfiddle.com/#!2/ef680

3 个答案:

答案 0 :(得分:0)

没有评论私人......

ID 4和6在时间表中有两行吗?其他人只有一个?然后task.hrs会加倍。

这样的事情应该避免这种情况。 如果task_id是唯一的,则不必总结。  (测试数据会有所帮助)

修改

SELECT
        ts.staff_id,
        task.assigned_to,
        task.hrs AS assigned_hrs,
        ts.name,
        ts.actual_hours
    FROM task
    INNER JOIN (SELECT staff_id, name, SUM(hours) as actual_hours FROM timesheet GROUP BY staff_id, name) as ts
    ON ts.staff_id = task.assigned_to

上述:按工作人员/名称分组的工作表时间表 然后加入任务,每个任务应该只有一行

答案 1 :(得分:0)

    SELECT
        timesheet.staff_id,
        task.assigned_to,
        SUM(task.hrs) AS assigned_hrs,
        timesheet.name,
        SUM(timesheet.hours) AS actual_hours
    FROM task
    LEFT JOIN timesheet ON timesheet.staff_id = task.assigned_to
    GROUP BY timesheet.staff_id

尝试LEFT JOIN并确保按UNIQUE字段分组。 “名称”可能不是唯一的。

注意:LEFT JOIN将遗漏未分配给任务的任何时间表。您可以通过SELECT FROM timesheet LEFT JOIN任务来反转它。

修改:请参阅以下答案:Select multiple sums with MySQL query and display them in separate columns

抱歉,还没有评论权限。

答案 2 :(得分:0)

SELECT x.*
     , SUM(y.hrs) n
  FROM
     ( SELECT t.staff_id
            , t.name
            , SUM(t.hours) actual_hours
         FROM timesheet t
        GROUP 
           BY t.staff_id
     ) x
  JOIN task y
    ON y.assigned_to = x.staff_id
 GROUP
    BY staff_id;

http://sqlfiddle.com/#!2/ef680/14