0

我有一个带有 4 个表的 MySQL 数据库:

job
job_application
client
candidate

每个表都有自己的主键,即job_id, job_application_id, client_id,candidate_id

表中的雇主可以在client表中发布职位job。该job表包含一个client_id标识客户的字段

表中的候选人candidate可以申请工作,在job_application表中插入一行。该job_application表包含一个job_id字段和一个candidate_id字段,用于标识工作是什么以及是谁申请的

我在为雇主编写查询以管理他们收到的工作申请时遇到了一些问题。作为一个例子,这里是我写的一个函数,它从job_application

public function deleteJobApplications($job_application_ids) {
    $this->db->query("DELETE ja.* FROM " . DB_PREFIX . "job_application ja LEFT JOIN " . DB_PREFIX . "job j ON (j.job_id = ja.job_id) WHERE ja.job_application_id IN ('" . implode("','", array_map('intval', $job_application_ids)) . "') AND j.client_id = '" . (int)$this->client->getClientId() . "'");
}

因为client_id只在表中引用,job所以LEFT JOIN每次job想从表中UPDATEDELETE从表中都需要到job_application

我应该client_id向表中添加另一个字段job_application,本质上是复制数据库中已经保存的数据,还是继续LEFT JOINfor every UPDATEand DELETE

4

2 回答 2

2

您的问题在于您需要通过将“client_id”作为冗余列引入来非规范化“job_applications”。(目前接受的答案在这方面实际上是不正确的。)您的问题是您一开始没有正确规范化。如果您,则“client_id”列将已经在该表中,并且您的问题一开始就不会出现。

让我们假设候选人姓名、客户姓名和职位名称是全球唯一的。

看起来像这样的表将满足名为“candidate_name”的谓词 Person 在公司“client_name”申请“job_name”。

job_applicatons
Person named <candidate_name> applies for <job_name> at company <client_name>.

client_name  job_name                candidate_name  
--
Microsoft    C++ programmer, Excel   Ed Wood 
Microsoft    C++ programmer, Excel   Dane Crute 
Microsoft    C++ programmer, Excel   Vim Winder
Microsoft    C++ programmer, Word    Wil Krug
Microsoft    C++ programmer, Word    Val Stein
Google       Python coder, search    Ed Wood
Google       Programmer, compilers   Ed Wood
Google       Programmer, compilers   Val Stein

三列,没有 id 号,没有空值,没有非主属性,都是键。这种关系在 6NF 中。

很明显,您可以通过从前两列中选择不同的值来为工作(或工作机会)创建一个表。外键引用是显而易见的。

jobs
Company named <client_name> offers <job_name>.

client_name  job_name
--
Microsoft    C++ programmer, Excel
Microsoft    C++ programmer, Word
Google       Python coder, search
Google       Programmer, compilers

以类似的方式,您可以仅从第一列中为一组公司选择不同的值,而从最后一列中为一组申请人选择不同的值。同样,外键引用应该是显而易见的。

clients
Company named <client_name> is a client.

client_name
--
Microsoft
Google

candidates
Person named <candidate_name> is looking for a job.

candidate_name  
--
Ed Wood 
Dane Crute 
Vim Winder
Wil Krug
Val Stein

所有这些表都在 6NF 中。

当您正确执行时,除了自然键之外,使用代理键来扩充表不会改变正常形式。让我们用您的代理 ID 号替换“job_applications”中的自然键。进行替换将使您的表格看起来像这样。(实际上,您也会在其他表中做同样的事情。)

job_applications
--
client_id
job_id
candidate_id
primary key (client_id, job_id, candidate_id)
other columns go here...

请注意,client_id 已经存在。如果没有其他列,则您至少仍处于 5NF 中。

于 2013-01-16T15:01:26.733 回答
0

要回答您的问题,这取决于您的情况,特别是桌子的大小是否值得。这个过程称为非规范化。例如,您可以在这里获得信息: http ://en.wikipedia.org/wiki/Denormalization

于 2013-01-14T13:28:38.620 回答