Как использовать MySQL Group By в этом случае? - PullRequest
1 голос
/ 14 сентября 2011

У меня есть таблицы, содержащие следующие поля, среди прочего, в приложении для транспортной компании ...

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 и поле user_type в таблице jempe_users ссылаются на таблицу jempe_user_types.

Таблица employee_clock_events используется для включения и выключения сотрудников во время их смены.Поле ece_type является enum ('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 ]

2 голосов
/ 14 сентября 2011

Ваша проблема заключается в определении того, какое последнее событие в часах приходится на сотрудника. Эта часть проблемы может быть решена следующим образом:

 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')

Затем вы можете СОВМЕСТИТЬ содержимое этого второго представления с вашими другими таблицами, чтобы получить другую информацию и взять записи ТОП 3 для ваших трех возможных драйверов.

Обратите внимание, что вы можете сделать все это в одном, более сложном запросе, но я думаю, что понятие "текущий статус сотрудника" является важным и достаточно многократно используемым, поэтому стоит инкапсулировать логику в представлении.

Окончательное решение (где вы присоединяетесь к таблицам вместе) не будет использовать GROUP BY. Это связано с тем, что GROUP BY необходимо использовать относительно рано в алгоритме решения, чтобы создать список идентификаторов сотрудников и самых последних значений даты и времени; этот список затем присоединяется к таблице сотрудников, чтобы получить список самых последних записей из этой таблицы.

0 голосов
/ 14 сентября 2011

Мне нужно проверить это дальше, но я закончил с этим ...

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

Кажется, до сих пор он работал правильно.Я еще не смог заставить работать мнение Ларри, но я проверю его позже.Если это сработает, я отмечу его ответ как правильный.Кто-нибудь видит что-то не так с этим?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...