简答:候选键为(A,F)、(B,F)和(D,F ).
像这样Wikipedia article 说:
可以计算所有候选键的集合,例如从一组
功能依赖。为此我们需要定义属性
属性集α的闭包α+。套装
α+ 包含功能上的所有属性
由α暗示。
找到一个候选键非常简单。我们从一个
设置 α 个属性并尝试依次删除每个
属性。如果在删除属性后属性闭包
保持不变,那么这个属性不是必需的,我们可以
永久删除。我们称结果为 minimize(α)。如果 α 是所有属性的集合,则 minimize(α) 是候选键。
所以现在我们只需要把它付诸实践。让我们从所有属性 α0=(A,B,C,D,E,F)开始。现在我们可以看看删除 A 是否会产生问题。 α'0=(B,C,D,E,F), α'0+ sup> 是 (B,C,D,E,F,A)(因为 D→ A 成立)。现在通过永久踢出 A 并尝试删除 B,我们将得到 a 候选键。
-
α1=(B,C,D,E,F)。我们可以扔掉B吗?是的,因为 α'1=(C,D,E,F) 将导致 α'1+=(A,B,C,D,E,F)(因为 D→A 和 A→BCD)。
-
α2=(C,D,E,F)。我们可以扔掉 C 吗?是的,因为 α'2=(D,E,F) 将导致 α'2+=(A,B,C,D,E,F)(因为 D→A 和 A→BCD)。
-
α3=(D,E,F)。我们可以扔掉 D 吗?否,因为 α'3=(E,F) 将导致 α'3+= (E,F).
-
α3=(D,E,F)。我们可以扔掉E吗?是的,因为 α'3=(D,F) 将导致 α'3+= (A,B,C,D,E,F)(从 D→A;A→BCD;和 BC→DE em>)。
-
α4=(D,F)。我们可以扔掉F吗?不,因为 α'4=(D) 将导致 α'4+=(A ,B,C,D,E)(自D→A;A→BCD;和BC→DE)。
所以现在我们生成了 minimize(α0)=α4=(D,F)。我们可以使用 brute force 方法,在每次迭代中,我们遍历所有可以删除的可能键。但这将花费指数时间来生成。
Wikipedia 文章包含了一种生成所有候选键多项式键的数量和函数依赖关系的方法。算法定义为:
function find_candidate_keys(A, F)
/* A is the set of all attributes and F is the set of functional dependencies */
K[0] := minimize(A);
n := 1; /* Number of Keys known so far */
i := 0; /* Currently processed key */
while i < n do
foreach α → β ∈ F do
/* Build a new potential key from the previous known key and the current FD */
S := α ∪ (K[i] − β);
/* Search whether the new potential key is part of the already known keys */
found := false;
for j := 0 to n-1 do
if K[j] ⊆ S then found := true;
/* If not, add if
if not found then
K[n] := minimize(S);
n := n + 1;
i := i + 1
return K
所以如果我们运行算法,我们首先必须计算 minimize(A),但好消息是:我们已经在上面做了。所以 K[0] = (D,F), n=1 和 i=0。
现在我们使用 while 循环并开始迭代所有函数依赖项。
- 对于A→ BCD。所以现在我们构造一个键(A,F)。我们检查是否已经有一个子集定义为键(不是这种情况)。现在我们将其最小化,例如:(A,F)→(A,F)。所以我们添加了一个新的键(A,F)。
- 对于BC→DE。所以现在我们构造一个键(B,C,F)。我们检查是否已经有一个子集定义为键(不是这种情况)。现在我们将其最小化,例如 (B,C,F)→(B,F)→(B,F)。所以我们添加 (B,F)。
- 为B→D。所以现在我们构造一个键(B,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 为D→A。所以现在我们构造一个键(D,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
这是第一次迭代的结束。所以 K 现在是 K=[(D,F),(A,F),(B,F)]。 n=3 现在是 i=1。所以对于 K[i]=(A,F) 我们现在迭代:
- 对于A→ BCD。所以现在我们构造一个键(A,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 对于BC→DE。所以现在我们构造一个键(B,C,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 为B→D。所以现在我们构造一个键(A,B,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 为D→A。所以现在我们构造一个键(D,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
这是第二次迭代的结束。所以 K 现在是 K=[(D,F),(A,F),(B,F)]。 n=3 和现在 i=2。所以对于 K[i]=(B,F) 我们现在迭代:
- 对于A→ BCD。所以现在我们构造一个键(A,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 对于BC→DE。所以现在我们构造一个键(B,C,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 为B→D。所以现在我们构造一个键(B,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
- 为D→A。所以现在我们构造一个键(B,D,F)。我们检查是否已经有一个子集定义为键(就是这种情况)。我们不添加这个。
所以最后 K=[(D,F),(A,F),(B,F)]。这些都是候选键。