2011-09-14 13 views
1

私は運送会社のためのアプリケーションでは特に、次のフィールドを含むテーブルを持っている...このインスタンスでMySQL 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   | 
+-----------------------+ 

私がしなければならないことは、現在働いていて、患者を迎えるために割り当てられる休憩時間ではない3人のドライバーを示唆することです。

jempe_usersテーブルには、輸送会社の従業員とクライアントが含まれています。ユーザー・タイプ表には、user_type_name =ドライバーとjempe_users表のuser_typeフィールドがjempe_user_types表を参照するレコードがあります。

employee_clock_eventsテーブルは、シフト中に従業員の入退時を記録するために使用されます。 ece_typeフィールドはenum( 'shift_start'、 'shift_brake'、 'shift_resume'、 'shift_stop')です。 ece_datetimeフィールドには、シフトイベントが発生したときのtimesatmpが格納されます。

私がする必要があるのは、現在働いているユーザーグループが16,17、または18のuser_groupにあり、最も最近のシフト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

問題は、従業員一人あたりの最新のクロックイベントを特定することです。次のような問題の一部を解決することができる。

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の記録を取るために戻ってあなたの他のテーブルに、第2のビューの内容を参加することができます。

すべての作業を1つのより複雑なクエリで行うことができますが、「従業員の現在のステータス」の概念は重要で再利用可能であると考えています。

最後の解決策(ここではテーブルを一緒にジョインする)では、GROUP BYは使用されません。これは、従業員IDと最新の日時の値のリストを作成するために、ソリューションアルゴリズムの比較的早い段階でGROUP BYを使用する必要があるためです。そのリストは従業員表に再び結合され、その表から最新のレコードのリストが取得されます。

+0

はい「shift_start」または「shift_resume」のいずれかの従業員ごとに最新のクロックイベントを取得することが問題でした。私はそれがグループが入った場所だと思っていました。私は助けに感謝しますが、私はこの見解が私を助けるとは確信していません。私は非常に間違っている可能性がありますが、それは常に全体のMAX(event_datetime)と1つの行を持っていないでしょうか?私の理解が外れているなら、私を修正してください。 –

+0

あなたは正しいです、それはビューです。ただし、2番目のクエリ(ビューでカプセル化することもできます)は、その最大のdatetimeを使用して元のクロックイベントテーブルに戻ってJOINし、最新のステータスを表示します。これをより明確にするように編集してみましょう。 –

+0

さて、元の1つのクエリを2つに分割し、2つ目のビューとそのビューを使用するクエリを分割しました。ビュー1は、従業員一人あたりの最大日時を検出します。ビュー2はその情報をメインクロックイベントテーブルに戻し、employee_clock_eventsと同じ列を持つレコードセットを生成しますが、従業員一人のレコード(最新のレコード)のみを含みます。最後に、現在実行中のドライバのみを検索する方法を示します。 –

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 

これまでのところ正しく動作しているようです。私はLarryの意見提示をまだ働かせることができませんでしたが、私は後でそれをチェックします。それがうまくいくと思われるなら、私は彼の答えを正しいものとしてマークします。誰かがこれに間違って何かを見ますか?

+0

あなたのソリューションは基本的に同じものです(少なくとも今朝の回答を修正した後)。このアプローチはうまくいきますが、(1)この情報を導き出すために使用されたアルゴリズムを分離して名前を付けるので(これは多くの場合、別の「エンティティ」(この場合はVIEW)にクロックイベントの最新のセットを持つという考えが大変ですプログラム内で名前付き関数を使うのと同じように)、(2)同じ情報がアプリケーションの他の場所で役立つことがわかるはずです。 –

関連する問題