-5

我有 4 个表格,如下所示

表:请假请求

+------------+----------+--------------+------------+----------------------+
| 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_fromand 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_fromapproved_to,它们在leave_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

哦,现在我们有一个问题。存在一对多的关系,所以现在我们在结果中重复了请假请求。我们需要以某种方式过滤掉它。你没有具体说明如何,所以我要做几个假设:你想知道“管理员”批准的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在同一个查询中有两个用于两个不同目的的表实例。所以我们需要区分它们。(请记住,我在这里盲目飞行,实际上无法测试任何这些。如果在此过程中遇到任何问题,请纠正我。我也是徒手编写这段代码,因为我没有 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在 initial 的范围内LEFT OUTER JOIN。但我想所有这一切也确实取决于数据的完整性,我无法保证。

还值得注意的是,"Jack"当值为"jack". 我没有在这段代码中进行任何字符串操作来实现这一点。如果值应该在数据中大写,则在数据中将其大写。

同样,我不能保证这个代码。但作为一个演练,它应该让你朝着正确的方向前进。正如我在对该问题的评论中提到的,如果您要编写 MySQL 代码,我真的建议您拿起一本关于 MySQL 的书。

编辑:我可以给出的一项建议是数据本身的结构。具体来说,leave_approval那张桌子感觉有点乱,只有那张桌子引起了混乱。我有几个建议:

  1. approval_typeleave_approval表中添加一个。至少这将表明它是管理员批准、人力资源批准还是任何其他类型的批准。(甚至还有其他类型吗?会有吗?)然后您还可以使用request_idandapproval_type作为组合主键,或者至少是组合唯一约束,以加强数据完整性并防止重复批准。
  2. 如果只有两种批准并且可能不会改变,请将它们都反映在leave_approval表格中。有一组用于 的列admin_approval_*,一组用于hr_approval_*。(每组都将包括staff_id批准的相关日期。)然后request_id它本身可能是leave_approval使其与 . 一对一的主键leave_request。这将极大地简化关系数据,实质​​上将记录转换为leave_approval记录的一组可选附加信息leave_request。连接会变得更简单,数据会更清楚地表达自己。
于 2012-07-10T11:01:16.000 回答