MySQL按日期范围分组,具有多个连接

时间:2011-07-23 11:53:29

标签: mysql

我目前有一个非常混乱的查询,它连接来自涉及两个子查询的多个表的数据。我现在需要按DAY()WEEK()MONTH()QUARTER()对这些数据进行分组。

我有三个表:daysqosemployeesemployee是不言自明的,day是员工在某一天的表现的摘要,而qos是随机质量检查,可以每天执行多次。

目前,我正在选择所有employeesLEFT JOIN dayqos,效果很好。但是,现在,我需要对数据进行分组,以便在一个日期范围内细分团队或个人的表现。

获取此数据:

员工

id  | name
------------------
1   | Bob Smith

日期

id  | employee_id  | day_date   | calls_taken
---------------------------------------------
1   | 1            | 2011-03-01 | 41
2   | 1            | 2011-03-02 | 24
3   | 1            | 2011-04-01 | 35

的Qos

id   | employee_id  | qos_date   | score
----------------------------------------
1    | 1            | 2011-03-03 | 85
2    | 1            | 2011-03-03 | 95
3    | 1            | 2011-04-01 | 91

如果我从DAY()分组开始,我需要看到以下结果:

Day__date  | Day__Employee__id | Day__calls | Day__qos_score
------------------------------------------------------------
2011-03-01 | 1                 | 41         | NULL
2011-03-02 | 1                 | 24         | NULL
2011-03-03 | 1                 | NULL       | 90
2011-04-01 | 1                 | 35         | 91

如您所见,Day__calls应为SUM(calls_taken)Day__qos_scoreAVG(score)。我尝试过使用与上面类似的方法,但由于日期在其中一个表已加入之前是未知的,因此只显示保存day的记录。

有没有办法做到这一点,或者我是以错误的方式处理事情?

编辑:根据要求,这是我到目前为止所提出的内容。但是,它只显示有day的日期。

SELECT COALESCE(`day`.day_date, qos.qos_date)      AS Day__date,
      employee.id                                  AS Day__Employee__id,
      `day`.calls_taken                            AS Day__Day__calls,
      qos.score                                    AS Day__Qos__score
FROM   faults_employees `employee`
      LEFT JOIN (SELECT `day`.employee_id                    AS employee_id,
                        SUM(`day`.calls_taken)               AS `calls_in`,
                 FROM   faults_days AS `day`
                 WHERE employee.id = 7
                 GROUP  BY (`day`.day_date)
        ) AS `day`
        ON `day`.employee_id = `employee`.id
      LEFT JOIN (SELECT `qos`.employee_id AS employee_id,
                        AVG(qos.score)   AS `score`
                 FROM   faults_qos qos
                 WHERE employee.id = 7
                 GROUP  BY (qos.qos_date)
        ) AS `qos`
        ON `qos`.employee_id = `employee`.id AND `qos`.qos_date = `day`.day_date
WHERE employee.id = 7
GROUP  BY Day__date
ORDER BY `day`.day_date ASC

1 个答案:

答案 0 :(得分:2)

我正在提出的解决方案如下:

SELECT
    `date`,
    `employee_id`,
    SUM(`union`.`calls_taken`) AS `calls_taken`,
    AVG(`union`.`score`) AS `score`
FROM ( -- select from union table
    (SELECT -- first select all calls taken, leaving qos_score null
        `day`.`day_date` AS `date`,
        `day`.`employee_id`,
        `day`.`calls_taken`,
        NULL AS `score`
    FROM `employee`
    LEFT JOIN
        `day`
            ON `day`.`employee_id` = `employee`.`id`
    )
    UNION -- union both tables
    (
    SELECT -- now select qos score, leaving calls taken null
        `qos`.`qos_date` AS `date`,
        `qos`.`employee_id`,
        NULL AS `calls_taken`,
        `qos`.`score`
    FROM `employee`
    LEFT JOIN
        `qos`
            ON `qos`.`employee_id` = `employee`.`id`
    )
) `union`
GROUP BY `union`.`date` -- group union table by date

要使UNION生效,我们必须将qos_score表中的day字段和calls_taken表中的qos字段设置为null 。如果我们不这样做,calls_takenscore将被UNION语句选入同一列。 在此之后,我从union'd表中选择了具有聚合函数SUM()AVG()的必填字段,并按联合表中的date字段进行分组。