2

MySql 5.5。

仕事の割り当てを表すテーブルがあります。

   empId   jobNo   workDate   hours
     4      441    10/1/2012    10
     4      441     9/1/2012    22
     4      441     8/1/2012     6

そして、給与を表すもの:

   empId   effDate     rate
     4     10/1/2012    6.50
     4      9/1/2012    5.85
     4      6/1/2012    4.00

給与は、発効日以降に実行されたすべての作業に適用されます。したがって、6 月、7 月、8 月のレートは 4.00 です。9 月は 5.85、10 月は 6.50 です。

単純に 10 月の作業をクエリすると、次のようになります。

   SELECT Work.empId, Work.jobNo, Work.workDate, Work.hours, Salary.effDate, Salary.rate
   FROM Work
   JOIN Salary ON Work.empId = Salary.empId
   WHERE Work.workDate <= '2012-10-01'
      AND Salary.effDate <= Work.workDate
   ORDER BY Work.jobNo ASC, Work.workDate DESC;

欲しいものが手に入らない。私は次のようなものを手に入れます

   4   441   10/1/2012   10   10/1/2012   6.50
   4   441   10/1/2012   10    9/1/2012   5.85
   4   441   10/1/2012   10    6/1/2012   4.00
   4   441    9/1/2012   22    9/1/2012   5.85
   4   441    9/1/2012   22    6/1/2012   4.00
   4   441    8/1/2012    6    6/1/2012   4.00

したいとき

   4   441   10/1/2012   10   10/1/2012   6.50
   4   441    9/1/2012   22    9/1/2012   5.85
   4   441    8/1/2012    6    6/1/2012   4.00

必要なクエリを作成する方法について頭を悩ませることはできません。
実際の状況には、明らかに複数の従業員、複数の仕事があります。

ご協力いただきありがとうございます。

4

3 に答える 3

5

実際の問題は次のとおりです。Work の各レコードについて、勤務日 x 給与有効日に従って、対応する有効レートを検出できるようにしたいと考えています。単純に行うSalary.effDate <= WORK.workDateと、勤務日の前にすべてのレートを取得できます。ただし、最新のものだけが必要です。

の最大 n 問題の少し複雑な変形です。これには多くの方法がありますが、ここではその 1 つを示します。

SELECT sel.*, Salary.Rate
FROM
(
     SELECT Work.empId, Work.jobNo, Work.workDate, 
           Work.hours, Max(Salary.effDate) effDate
    FROM WORK
    JOIN Salary ON WORK.empId = Salary.empId
    WHERE WORK.workDate <= '2012-10-01'
       AND Salary.effDate <= WORK.workDate
    GROUP BY WORK.empId, WORK.jobNo, WORK.workDate, WORK.hours
    ORDER BY WORK.jobNo ASC, WORK.workDate DESC
) sel 
INNER JOIN Salary ON sel.empId = Salary.empId 
                  AND sel.EffDate = Salary.EffDate

まず、内部クエリは、各勤務レコードの最新の給与発効日を検出します。次に、それを給与と再びレートに結合します。

動作中のSQLFiddleを参照してください。

于 2012-08-15T16:12:51.283 に答える
0

NATURALJOINと呼ばれるものを使用しています。「JOIN」という単語を「LEFTJOIN」に変更してみてください。これにより、左側の結果がグループ化され、目的の結果が得られます。

于 2012-08-15T15:59:20.553 に答える
0

empId給与テーブルに列と列で構成される主キーまたは代替キー (一意のインデックス) があると仮定すると、次のeffDateようになります。

select w.empID                   as EMPLOYEE_ID   ,
       w.jobNo                   as JOB_NUMBER    ,
       w.workDate                as DATE_WORKED   ,
       w.hours                   as HOURS_WORKED  ,
       rate.HourlyWage           as HOURLY_WAGE   ,
       w.hours * rate.HourlyWage as WAGES_CHARGED ,
       rate.effDateFrom          as HOURLY_WAGE_EFFECTIVE_DATE
from work w
join ( select sfrom.EmpId   as EmpID ,
              sfrom.rate    as HourlyWage ,
              sfrom.EffDate as effDateFrom ,
              ( select min(Effdate) 
                from salary t
                where t.empId   = sfrom.EmpId
                  and t.effDate > sfrom.EffDate
              ) as effDateThru
              from salary sfrom
     ) rate on rate.empID = w.empID
           and rate.EffDateFrom <= w.workDate
           and (    rate.effDateThru is null      -- if rate has not end date, is the current period
                 or rate.effDateThru > w.workDate -- 'date-thru' represents the start date of the next period, so the this upper bound is EXCLUSIVE
               )

rate各従業員の賃金と有効な日付範囲を提供する仮想テーブルに対して作業テーブルを結合します。各従業員の「現在」の行には、期限/有効期限が に設定されnullます。そして...有効期限日は実際には次の給与エントリの有効日であるため、上限は包括的ではなく排他的です。したがって、範囲テストは null をテストする必要があり、使用できませんbetween

于 2012-08-15T18:53:33.473 に答える