MySQLでの経験期間の計算

あるフォーラムでは、従業員の経験を考慮して、MySQLの日付差を正しく計算する方法について質問しました。 一見すると、質問は単純なものであることが判明しましたが、詳しく調べると、すべてがより興味深いものであることが判明しました。



問題

そもそも、おなじみの人事担当者数人と話をして、労働者の保険年功期間を考慮することは、私たちの国でどのように慣習的であるかについて尋ねました。 結局のところ、すべてがそれほど単純ではありません。 法律によれば、経験期間は次のように考慮されます。30日ごとに月に変換され、12か月ごとに年に変換されます。 しかし、それでも、別のスキームによる保険経験の会計処理は広く行われています-完全な月と年がそのまま考慮され、不完全な初期および最終月を構成する日が加算され、30日間の月に変換されます。 それは後者の方法のリリースについてであり、私は伝えたいです。



解決策

このアルゴリズムを、開始日と終了日という2つの入力パラメーターを持つストアド関数として設計することにしました。 作業の結果は文字列dd.mm.yyになりますが、「y年、m月、d日」の形式は日付の違いにより適しています。 スペースを節約し、些細な作業に気を取られないようにするために、このトピックに人間が読める行を作成しました。 入力パラメーターの考えられるすべてのバリエーションを2つのケースに分けました。1つ目は日付が1か月で、2つ目は別々です。 前者の場合、日付の差は日単位で発生します。 2番目のケースでは、日付間の月の差(マイナス1か月)を計算する必要があります。また、開始日の月の終わりと終了日の月の日までに欠落している日数の合計も計算する必要があります。 コードは次のとおりです。

CREATE FUNCTION `fNaturalDateDiff` ( iStartDate DATE , iFinalDate DATE )

RETURNS varchar ( 255 )

DETERMINISTIC

CONTAINS SQL

SQL SECURITY DEFINER

COMMENT ''

BEGIN

DECLARE aDays , aMonths INTEGER ;



IF DATE_FORMAT ( iStartDate , ' % Y % m' ) = DATE_FORMAT ( iFinalDate , ' % Y % m' ) THEN

SET aDays = DATEDIFF ( iFinalDate , iStartDate ) + 1 ;

SET aMonths = 0 ;

ELSE

SET aDays = DATEDIFF ( LAST_DAY ( iStartDate ) , iStartDate ) + DAYOFMONTH ( iFinalDate ) + 1 ;

SET aMonths = PERIOD_DIFF ( DATE_FORMAT ( iFinalDate , ' % Y % m' ) , DATE_FORMAT ( iStartDate , ' % Y % m' ) ) - 1 ;

END IF ;

SET aMonths = aMonths + aDays DIV 30 ;

SET aDays = aDays % 30 ;

RETURN CONCAT ( LPAD ( aDays , 2 , '0' ) , '.' , LPAD ( aMonths % 12 , 2 , '0' ) , '.' , LPAD ( aMonths DIV 12 , 2 , '0' ) ) ;

END ;








二番目の質問

1つの作業期間を見つけるには、この関数で十分ですが、同じアルゴリズムを使用して複数の作業期間の合計を計算する必要がある場合はどうすればよいでしょうか。 これを行うには、3つのストアドプロシージャを実行する必要があります。最初の(fCountFullMonths)は指定された期間の完全な月数を差し引き、2番目(fCountCutOffDays)は最初の関数(期間の開始と終了)でカウントされない日数を差し引きます、そして3番目( fFormatPeriod)-最初のパラメーターとして月数を、2番目として日数を取り、30日ごとの月への変換、および12か月から年への変換を考慮して、このデータを出力用の便利な文字列にフォーマットします。

これらの機能を使用すると、従業員の勤続期間の合計を計算することは難しくありません。

SELECT Person , fFormatPeriod ( SUM ( fCountFullMonths ( StartDate , EndDate ) ) , SUM ( fCountCutOffDays ( StartDate , EndDate ) ) ) FROM experience WHERE Person = ...





ここではこれらの関数の実装を説明しません。 上記の機能を「分解」することで、簡単に作成できます。



All Articles