0

1. emp_ot テーブルを使用して、従業員が特定の期間内に行うことができる ot 時間の最大量を定義します

2. Daily_attend実際に何が起こっているかを説明します

3.私のテーブルは次のように短縮されました

mysql> select punchDate,empNO,ot from daily_attend;
+------------+--------+----------+
| punchDate  | empNO  | ot       |
+------------+--------+----------+
| 2012-02-20 | 000123 | 02:00:00 |
| 2012-02-02 | 000123 | 01:00:00 |
| 2012-02-01 | 000126 | 01:00:00 |
| 2012-02-01 | 000123 | 01:00:00 |
+------------+--------+----------+
4 rows in set (0.01 sec)

mysql> select permitId,permitMonth,empNo,dayFrom,dayTO,permitOt from 
emp_ot;
+----------+-------------+--------+------------+------------+----------+
| permitId | permitMonth | empNo  | dayFrom    | dayTO      | permitOt |
+----------+-------------+--------+------------+------------+----------+
|        1 |          02 | 000123 | 2012-02-01 | 2012-02-10 | 02:00:00 |
|        2 |          02 | 000123 | 2012-02-20 | 2012-02-25 | 03:00:00 |
|        3 |          02 | 000126 | 2012-02-01 | 2012-01-10 | 02:00:00 |
|        4 |          03 | 000123 | 2012-03-01 | 2012-03-10 | 05:00:00 |
+----------+-------------+--------+------------+------------+----------+
4 rows in set (0.00 sec) 

4.ここで、 emp_ot.workedOtを更新して、従業員が各permitIdの下で何時間働いたかを知りたい

元:

+----------+------------+----------+----------+
| permitId |  empNo     | workedOt | permitOt |
+----------+----------+----------+----------+
|        1 |  000123    | 02:00:00 | 02:00:00 |
|        2 |  000123    | 02:00:00 | 03:00:00 |
|        3 |  000126    | 01:00:00 | 02:00:00 |
|        4 |  000123    | 00:00:00 | 05:00:00 |
+----------+------------+----------+----------+

5.毎日00:00:01に実行されるmysqlイベントを使用しています。これは、テーブルが古いデータを台無しにすることなく自動的に更新される必要があるためです

6.次のように試してください:

    DROP EVENT IF EXISTS make_emp_ot;

    DELIMITER |



    CREATE EVENT make_emp_ot

        ON SCHEDULE EVERY 1 DAY STARTS 
TIMESTAMP(CURRENT_DATE,'00:00:01')

        DO

          BEGIN 

        INSERT INTO emp_ot( permitMonth,empNo, dayFrom, dayTo, workedOt)

             SELECT  o.permitId,EXTRACT(MONTH FROM CURRENT_DATE)AS 
permitMonth ,o.empNo,'','',(
               SELECT ifnull( SEC_TO_TIME(SUM(TIME_TO_SEC(d.ot))) 
,'00:00:00')  

               FROM  daily_attend d

               WHERE d.punchDate BETWEEN o.dayFrom  AND o.dayTo
               GROUP BY o.empNo)AS ot

             FROM emp_ot o

             LEFT JOIN daily_attend d on o.empNo=d.empNo

             WHERE o.permitMonth=EXTRACT(MONTH FROM CURRENT_DATE)
          ON DUPLICATE KEY UPDATE

          workedOt=VALUES(workedOt) ;
    END; |


    DELIMITER ;

7.テーブルの結合に問題があると思われますが、実際には挿入部分が必要ありません。更新部分のみを使用するにはどうすればよいですか?

8.これらのことを修正するのを手伝ってください.皆さんありがとう.

4

1 に答える 1

0
  1. テーブルは古いデータを台無しにすることなく自動的に更新する必要があるため、毎日00:00:01に駆動されるmysqlイベントを使用しています

    トリガーの使用を検討しましたか?

  2. テーブルの結合に問題があると思われます

    あなたのINSERT ... ON DUPLICATE KEY UPDATE声明には多くの問題があります:

    • INSERTこの部分では 5 列しか指定していませんが、 SELECT6 列が返されます (意図していなかったのではないでしょうかSELECT permitId;

    • 空の文字列は、列と列''に挿入するための有効な日付リテラルではありません(それらが MySQL の型であると仮定します)。dayFromdayToDATE

    • 外部クエリは 1 つのGROUP BYレコードのみを想定しているため、サブクエリ内ではあまり意味がありません。そのレコードセットを一致するものに制限し、empNoその句を削除する必要がありGROUP BYます (すべての行は集計関数によって暗黙的にグループ化されます)。

    • 相関サブクエリがあるため、外側のクエリでテーブルを結合することは不要であり、誤りです (ただし、このような結合を使用してから外側のクエリをグループ化することで、相関サブクエリを使用せずに同じ結果を得ることができます。これにより、パフォーマンスが向上します)。

    • パーツが期待どおりに機能UNIQUEするために適切なキーが定義されているかどうかは明確ではありません。ON DUPLICATE KEY UPDATE

    そして実際には、挿入部分は必要ありません。更新部分のみを使用するにはどうすればよいですか?

    UPDATEの代わりに使用INSERT:

    UPDATE emp_ot e
    SET    permitOt := (
             SELECT IFNULL(SEC_TO_TIME(SUM(TIME_TO_SEC(d.ot))),0)
             FROM   daily_attend d
             WHERE  d.empNo = e.empNo
                AND d.punchDate BETWEEN e.dayFrom AND e.dayTO
           )
    WHERE  permitMonth = EXTRACT(MONTH FROM CURRENT_DATE)
    

    sqlfiddleで参照してください。

于 2012-12-09T07:58:41.953 に答える