-5

以下に示すような4つのテーブルがあります

表: leave_request

+------------+----------+--------------+------------+----------------------+
| request_id | staff_id | applied_from | applied_to | status               |
+------------+----------+--------------+------------+----------------------+
|      1     |   10     | 01-07-2012   | 02-07-2012 | approved             |
|      2     |   12     | 02-07-2012   | 02-07-2012 | awaiting HR approval |
+------------+----------+--------------+------------+----------------------+

表: leave_approval

+-------------+-------------+---------------+-------------+
| request_id  | approved_by | approved_from | approved_to |
+-------------+-------------+---------------+-------------+
|    1        |      1      |  01-07-2012   |  02-07-2012 |
|    1        |      2      |  01-07-2012   |  02-07-2012 |
|    2        |      1      |  02-07-2012   |  02-07-2012 | 
+-------------+-------------+---------------+-------------+

表:スタッフ

+-----------+-------+----------+
| staff_id  | name  | group_id |
+-----------+-------+----------+
|    1      | jack  |     1    |
|    2      | jill  |     2    |
|    10     | sam   |     3    | 
|    12     | david |     3    |
+-----------+-------+----------+

表:グループ

+-----------+------------+
| group_id  | group_name |
+-----------+------------+
|    1      |    admin   |
|    2      |     HR     |
|    3      |    staff   | 
+-----------+------------+

これらのテーブルを結合してレポートを作成する必要があります。次のようになります。

+----------+------------+----------+-------------+-----------+--------------+-----------+
|applied_by|applied_from|applied_to|approved_from|approved_to|approved_admin|approved_hr|
+----------+------------+----------+-------------+-----------+--------------+-----------+
|   sam    | 01-07-2012 |02-07-2012|01-07-2012   |02-07-2012 | Jack         | Jill      |
|   david  | 02-07-2012 |02-07-2012|02-07-2012   |02-07-2012 | Jack         | null      |
+----------+------------+----------+-------------+-----------+--------------+-----------+

前もって感謝します :)

4

1 に答える 1

1

ステップバイステップで見ていきましょう...

まず、選択しているエンティティがleave_requestテーブルにあります。それでは、そこから始めましょう。

SELECT leave_request.* FROM leave_request

applied_byここで、目的の結果の列のデータを知る必要があります。だからあなたはstaffテーブルに参加します:

SELECT
  applied_staff.name AS applied_by
FROM
  leave_request
  INNER JOIN staff AS applied_staff ON leave_request.staff_id = applied_staff.staff_id

(テーブル名にエイリアスを使用していることに注意してください。これは後で役立ちます。)

今、あなたはあなたがすでに利用できることを知る必要がapplied_fromあります:applied_to

SELECT
  applied_staff.name AS applied_by,
  leave_request.applied_from,
  leave_request.applied_to
FROM
  leave_request
  INNER JOIN staff AS applied_staff ON leave_request.staff_id = applied_staff.staff_id

ここで、テーブルにあるapproved_fromとを知る必要があります。approved_toleave_approval

SELECT
  applied_staff.name AS applied_by,
  leave_request.applied_from,
  leave_request.applied_to,
  admin_approval.approved_from,
  admin_approval.approved_to
FROM
  leave_request
  INNER JOIN staff AS applied_staff ON leave_request.staff_id = applied_staff.staff_id
  INNER JOIN leave_approval AS admin_approval ON leave_request.request_id = admin_approval.request_id

ええと、今私たちは問題を抱えています。1対多の関係があるため、結果に休暇申請を複製しました。どういうわけかそれをフィルタリングする必要があります。方法を指定しないので、いくつかの仮定を立てます。「管理者」の承認を知りたいのですが、「管理者」の承認は1つだけです。approved_fromapproved_to

これらの仮定をテーブル結合に反映させましょう。

SELECT
  applied_staff.name AS applied_by,
  leave_request.applied_from,
  leave_request.applied_to,
  admin_approval.approved_from,
  admin_approval.approved_to
FROM
  leave_request
  INNER JOIN staff AS applied_staff ON leave_request.staff_id = applied_staff.staff_id
  INNER JOIN leave_approval AS admin_approval ON leave_request.request_id = admin_approval.request_id
  INNER JOIN staff AS approved_staff ON admin_approval.approved_by = approved_staff.staff_id
  INNER JOIN group AS approved_staff_group on approved_staff.group_id = approved_staff_group.group_id
WHERE
  approved_staff_group.group_name = 'admin'

それは良いはずです。ここでstaffは、同じクエリで2つの異なる目的のためにテーブルの2つのインスタンスがあるため、テーブルのエイリアシングが便利であることに注意してください。したがって、それらを区別する必要がありました。(私はここで盲目的に飛んでいるので、実際にこれをテストすることはできません。途中で問題が発生した場合は修正してください。MySQLを持っていないため、このコードもフリーハンドで使用しています。便利なので、構文エラーがある場合もお知らせください。)

approved_admin次に、すでに利用可能な結果にフィールドを追加しましょう。

SELECT
  applied_staff.name AS applied_by,
  leave_request.applied_from,
  leave_request.applied_to,
  admin_approval.approved_from,
  admin_approval.approved_to,
  approved_staff.name AS approved_admin
FROM
  leave_request
  INNER JOIN staff AS applied_staff ON leave_request.staff_id = applied_staff.staff_id
  INNER JOIN leave_approval AS admin_approval ON leave_request.request_id = admin_approval.request_id
  INNER JOIN staff AS approved_staff ON admin_approval.approved_by = approved_staff.staff_id
  INNER JOIN group AS approved_staff_group on approved_staff.group_id = approved_staff_group.group_id
WHERE
  approved_staff_group.group_name = 'admin'

最後に、を知る必要がありapproved_hrます。そしてnull、許可されていますか?次に、これに別の結合を使用します。私も上記と同様の仮定をしています。これを試してみましょう:

SELECT
  applied_staff.name AS applied_by,
  leave_request.applied_from,
  leave_request.applied_to,
  admin_approval.approved_from,
  admin_approval.approved_to,
  approved_staff.name AS approved_admin,
  hr_staff.name AS approved_hr
FROM
  leave_request
  INNER JOIN staff AS applied_staff ON leave_request.staff_id = applied_staff.staff_id
  INNER JOIN leave_approval AS admin_approval ON leave_request.request_id = admin_approval.request_id
  INNER JOIN staff AS approved_staff ON admin_approval.approved_by = approved_staff.staff_id
  INNER JOIN group AS approved_staff_group on approved_staff.group_id = approved_staff_group.group_id
  LEFT OUTER JOIN leave_approval AS hr_approval ON leave_request.request_id = hr_approval.request_id
  LEFT OUTER JOIN staff AS hr_staff ON hr_approval.approved_by = hr_staff.staff_id
  LEFT OUTER JOIN group AS hr_staff_group ON hr_staff.group_id = hr_staff_group.group_id
WHERE
  approved_staff_group.group_name = 'admin'
  AND hr_staff_group.group_name = 'HR'

私はそれらの後者について完全にLEFT OUTER JOIN確信していません。最初のものは間違いなくnull値を許可する結合である必要がありますが、クエリエンジンがそれを超える結合をどのように処理するかはわかりません。私はそれらがINNER JOIN最初のの範囲内にあることを望みLEFT OUTER JOINます。しかし、それはすべてデータの整合性にも依存していると思いますが、これは保証できません。

"Jack"値が。の場合に出力として必要であると主張することも注目に値します"jack"。これを実現するために、このコードでは文字列操作を行いませんでした。値をデータで大文字にする必要がある場合は、データで大文字にします。

繰り返しますが、私はこのコードを保証することはできません。しかし、ウォークスルーとして、それはあなたが正しい方向に動くようになるはずです。質問へのコメントで述べたように、MySQLコードを書くつもりなら、MySQLに関する本を手に入れることを強くお勧めします。

編集:私が与えることができる1つの推奨事項は、データ自体の構造です。具体的には、そのleave_approvalテーブルは少し乱雑に感じられ、混乱を引き起こしているのはそのテーブルだけです。いくつかの推奨事項があります。

  1. テーブルにを追加approval_typeleave_approvalます。少なくとも、これは、それが管理者の承認、HRの承認、またはその他の種類の承認であるかどうかを示します。(他の種類もありますか?これまでにありますか?)次に、結合された主キー、または少なくとも結合された一意の制約として使用request_idして、データの整合性を高め、承認の重複を防ぐこともできます。approval_type
  2. 承認が2種類しかなく、それがおそらく変わらない場合は、両方をleave_approval表に反映します。の列を1セット、。の列をadmin_approval_*1セット用意しhr_approval_*ます。(各セットにはstaff_id、承認に関連する日付が含まれます。)次に、それ自体が、と1対1にするためrequest_idの主キーになる可能性があります。これにより、リレーショナルデータが劇的に簡素化され、基本的にレコードがレコードのオプションの追加情報セットに変わります。結合ははるかに単純になり、データはそれ自体をはるかに明確に表現します。leave_approvalleave_requestleave_approvalleave_request
于 2012-07-10T11:01:16.000 に答える