3

参照に関連するデータを発効日とともに要約する必要があります。

これらのテーブルを使用した給与スキーマを想像してみましょう

employee                                         work
+----+------+                                    +----+--------+------------+
| id | name |                                    | id | emp_id | date       |
+----+------+                                    +----+--------+------------+
|  1 | John |                                    |  1 |      1 | 2012-10-05 |
|  2 | Bob  |                                    |  2 |      1 | 2012-02-10 |
+----+------+                                    |  3 |      2 | 2012-09-03 |
                                                 |  4 |      1 | 2012-12-12 |
salary                                           |  5 |      1 | 2012-04-04 |
+----+--------+--------------+------------+      |  6 |      2 | 2012-06-09 |
| id | emp_id | daily_amount | start_date |      |  7 |      1 | 2012-07-24 |
+----+--------+--------------+------------+      +----+--------+------------+
|  1 |      1 |           10 | 2012-01-01 | 
|  2 |      1 |           15 | 2012-04-16 |
|  3 |      2 |           20 | 2012-05-25 |
+----+--------+--------------+------------+

2012-01-01からジョンは日ごとに10を支払われ、2012-04-16から彼の賃金は15に増額されます。
ボブは2012-05-25から20を支払われています。


ここで、2012年に両方の従業員の給与を計算する必要があるとしましょう。これが私の素朴な試みです。

SELECT
  emp.name AS "employee"
, SUM(sal.daily_amount) AS "amount"
FROM employee AS emp
JOIN work AS wrk ON (wrk.emp_id = emp.id)
JOIN salary AS sal ON (
  sal.emp_id = emp.id
  AND wrk.date >= sal.start_date
)
WHERE YEAR(wrk.date) = 2012
GROUP BY emp.id
;

もちろん、MAXを取っていないので欲しいものは出ませんstart_date

質問:2012年にボブとジョンが稼いだ金額はいくらですか?

4

2 に答える 2

3

SQLfiddleで以下をテストしました:

SELECT employee.name AS "employee",
       SUM(s1.daily_amount) AS "amount"
FROM work
  INNER JOIN salary s1
     ON work.emp_id = s1.emp_id
    AND work.date >= s1.start_date
  LEFT JOIN salary s2
     ON work.emp_id = s2.emp_id
    AND work.date >= s2.start_date
    AND s2.start_date > s1.start_date
  INNER JOIN employee
     ON work.emp_id = employee.id
WHERE s2.emp_id IS NULL
GROUP BY work.emp_id

s1との組み合わせを使用しs2て最終日を探すという考え方です。s1これは、勤務日の前の給与定義ですが、同様に適用される後の給与定義がない場合s2NULL限ります。

于 2012-12-07T13:48:29.297 に答える
2

さて、あなたはsalary table開始日がありますが、終了日も必要です。これは、派生テーブルを使用して行うことができます。

  SELECT
    s_1.emp_id,
    s_1.daily_amount,
    s_1.start_date AS start,
    DATE_ADD(MIN(s_2.start_date), INTERVAL -1 DAY) AS end
  FROM
    salary s_1
    LEFT JOIN salary s_2
      ON s_1.emp_id = s_2.emp_id AND s_1.start_date < s_2.start_date
  GROUP BY s_1.emp_id, s_1.start_date

最後に、次のようになります。

SELECT
  employee.name,
  SUM(s.daily_amount) AS amount
FROM
  employee
  JOIN work
    ON employee.id = work.emp_id
  JOIN
    (
      SELECT
        s_1.emp_id,
        s_1.daily_amount,
        s_1.start_date AS start,
        DATE_ADD(MIN(s_2.start_date), INTERVAL -1 DAY) AS end
      FROM
        salary s_1
        LEFT JOIN salary s_2
          ON s_1.emp_id = s_2.emp_id AND s_1.start_date < s_2.start_date
      GROUP BY s_1.emp_id, s_1.start_date
    ) AS s
    ON employee.id = s.emp_id
    AND
    work.date >= s.start
    AND
    (work.date <= s.end OR s.end IS NULL)
GROUP BY employee.id

なしで編集DATE_ADD()

SELECT
  employee.name,
  SUM(s.daily_amount) AS amount
FROM
  employee
  JOIN work
    ON employee.id = work.emp_id
  JOIN
    (
      SELECT
        s_1.emp_id,
        s_1.daily_amount,
        s_1.start_date AS start,
        MIN(s_2.start_date) AS end
      FROM
        salary s_1
        LEFT JOIN salary s_2
          ON s_1.emp_id = s_2.emp_id AND s_1.start_date < s_2.start_date
      GROUP BY s_1.emp_id, s_1.start_date
    ) AS s
    ON employee.id = s.emp_id
    AND
    work.date >= s.start
    AND
    (work.date < s.end OR s.end IS NULL)
GROUP BY employee.id
于 2012-12-07T13:59:28.337 に答える