在这种情况下如何使用MySQL Group By?

时间:2011-09-14 02:52:26

标签: mysql sql group-by

我在运输公司的申请表中包含以下字段的表格......

jempe_users

+------------------------------+
| Field                        |
+------------------------------+
| user_id                      |
| user_user_group_id           |
| user_type                    | 
| user_real_name               |
| user_drv_code                |
+------------------------------+

jempe_user_types:

+---------------------+
| Field               |
+---------------------+
| user_type_id        |
| user_type_name      |
+---------------------+

employee_clock_events:

+-----------------------+
| Field                 |
+-----------------------+
| ece_id                |
| ece_employee_id       |
| ece_type              |
| ece_datetime          |
| ece_active            |
+-----------------------+

我需要做的是建议三个目前正在工作而不是休息的司机,这些司机可以被分配来接送病人。

jempe_users表包含员工以及运输公司的一些客户。用户类型表有一条记录,其中user_type_name = driver和jempe_users表中的user_type字段引用了jempe_user_types表。

employee_clock_events表用于在轮班期间为员工提供进出时间。 ece_type字段是枚举('shift_start','shift_brake','shift_resume','shift_stop')。 ece_datetime字段存储转移事件发生的时间点。

所以我需要做的是在user_group 16,17或18中查找当前正在工作的驱动程序用户类型以及最近的移位ece_type是'shift_start'还是'shift_resume'。

我已经尝试了以下几十种变体,但似乎无法选择目前正在工作的员工。我似乎没有选择今天至少工作过的员工的问题。

尝试过这种变化...

SELECT user_id, driver_name, driver_code
FROM
(
    SELECT
        u.user_id AS user_id,
        u.user_real_name AS driver_name,
        u.user_drv_code AS driver_code,
        e.ece_type AS event_type,
        e.ece_datetime AS event_datetime
    FROM employee_clock_events AS e
    INNER JOIN jempe_users AS u 
        ON e.ece_employee_id = u.user_id
    LEFT JOIN jempe_user_types AS ut
        ON u.user_type = ut.user_type_id
    WHERE
        e.ece_shift_date = '2011-09-13'
        AND ut.user_type_name = 'driver'
        AND u.user_user_group_id IN (16, 17, 18)
        AND NOT ISNULL(u.user_drv_code)
        AND u.user_active = 1
) AS TEMPORARY
GROUP BY user_id
HAVING MAX(event_datetime)

这就是......

SELECT u.user_id AS user_id, u.user_real_name AS driver_name, u.user_drv_code AS driver_code, MAX(e.ece_datetime) AS current_event_datetime
FROM employee_clock_events AS e
LEFT JOIN jempe_users AS u 
    ON e.ece_employee_id = u.user_id
LEFT JOIN jempe_user_types AS ut
    ON u.user_type = ut.user_type_id
WHERE
    (e.ece_type = 'shift_start' OR e.ece_type = 'shift_resume')
    AND e.ece_shift_date = '2011-09-13'
    AND ut.user_type_name = 'driver'
    AND u.user_user_group_id IN (16, 17, 18)
    AND NOT ISNULL(u.user_drv_code)
    AND u.user_active = 1
GROUP BY e.ece_employee_id

我哪里错了?谢谢你的帮助。

2 个答案:

答案 0 :(得分:2)

您的问题是确定每位员工最近的时钟事件。这部分问题可以解决如下:

 CREATE VIEW MRClockByEmployee (ece_employee_ID, ece_most_recent_datetime) AS
    AS SELECT ece_employee_ID, MAX(ece_datetime) 
    FROM employee_clock_events
    GROUP BY ece_employee_id;

 CREATE VIEW MRClockInfoByEmployee 
     (ece_id, ece_employee_ID, ece_type, ece_datetime, ece_active) AS
 SELECT CE.* FROM employee_clock_events CE JOIN MRClockByEmployee MR
    ON CE.ece_employee_ID = MR.ece_employee_id AND
       CE.ece_datetime = MR.ece_most_recent_datetime

 SELECT ece_employee_id FROM MRClockInfoByEmployee
    WHERE type IN ('shift_start', 'shift_resume')

然后,您可以将第二个视图的内容加入到其他表中以获取其他信息,并为您的三个可能的驱动程序获取TOP 3记录。

请注意,您可以在一个更复杂的查询中完成所有这些操作,但我认为“员工当前状态”的概念非常重要且足够可重用,因此值得在视图中封装逻辑。

最终解决方案(将表连接在一起)不会使用GROUP BY。这是因为必须在解决方案算法中相对较早地使用GROUP BY才能创建员工ID列表和最近的日期时间值;然后将该列表连接回employee表,以获取该表中最新记录的列表。

答案 1 :(得分:0)

我需要进一步测试,但我最终还是继续这个......

SELECT u.user_id, u.user_real_name AS driver_name, u.user_drv_code AS driver_code
FROM
(
    SELECT ece_employee_id, MAX(ece_datetime) AS ece_datetime
    FROM employee_clock_events
    WHERE ece_active = 1 AND ece_shift_date = '2011-09-13'
    GROUP BY ece_employee_id
) AS mre
INNER JOIN employee_clock_events AS e
    ON e.ece_employee_id = mre.ece_employee_id AND e.ece_datetime = mre.ece_datetime
LEFT JOIN jempe_users AS u 
    ON e.ece_employee_id = u.user_id
LEFT JOIN jempe_user_types AS ut
    ON u.user_type = ut.user_type_id
WHERE
    (e.ece_type = 'shift_start' OR e.ece_type = 'shift_resume')
    AND e.ece_shift_date = '2011-09-13'
    AND ut.user_type_name = 'driver'
    AND u.user_user_group_id IN (16, 17, 18)
    AND NOT ISNULL(u.user_drv_code)
    AND u.user_active = 1

到目前为止似乎工作正常。我还没有能够得到拉里的观点建议,但我会稍后再查看。如果它似乎有用,我会将他的答案标记为正确。有没有人看到这个有什么问题?