datarekha

Finding Candidate Keys from FDs

Handed nothing but a tangle of functional dependencies, how do you find every key a table has? One short procedure does it every time — and GATE asks it almost every year.

8 min read Intermediate GATE DA Lesson 70 of 122

What you'll learn

  • A candidate key is a minimal attribute set whose closure is the whole relation
  • Sort attributes into LHS-only, RHS-only, and both — the split that shortcuts the search
  • The procedure that turns a set of FDs into every candidate key
  • Why LHS-only attributes sit in every key and RHS-only ones sit in none

Before you start

Last lesson closed on a reversal. Computing X⁺ confirms a key you already suspect — you start with X, watch its closure grow, and check whether it swallows every attribute. That is the easy direction. The hard one ran the other way: handed nothing but a tangle of functional dependencies, how do you find all the keys, not merely test a guess? That hunt is what this lesson is about.

Picture a school’s attendance register. To point at exactly one pupil, what do you need to know? The roll number alone will do it. So will a full name together with a date of birth and a home town, if the school is small enough that no two such pupils collide. Each of these is a little bundle of facts that pins down one row and no other.

A single table can carry several such bundles at once. Before you crown one of them the primary key, you would like the honest list of all of them — and guessing is not a method. The functional dependencies already hold the answer; we only need a procedure that reads it off. GATE leans on exactly this almost every year — how many candidate keys does R have, or which of these is one — so the procedure is worth owning cold.

Here is the picture to carry. Treat each attribute as a room, and each FD X → Y as a one-way door: once you are standing in all the rooms of X, that door swings open and lets you into Y. A bundle that pins down a row is then a set of rooms you can start in and, walking through doors, reach every room in the building. The smallest such starting set is the thing we are hunting.

A candidate key, defined

That smallest reach-everything starting set has a name: a candidate key. Precisely, it is a set of attributes K such that:

  1. K⁺ (its attribute closure) is the full set of attributes — K determines everything.
  2. No proper subset of K already determines everything — K is minimal.

Condition 1 makes K a superkey: enough to reach every room. Condition 2 trims that superkey down until nothing can be dropped. A relation can own more than one candidate key, and a key with n attributes does not promise that some (n-1)-attribute key also exists — minimality is checked subset by subset, never assumed.

The shortcut: where each attribute appears

Before computing a single closure, look at where each attribute lives in the FDs. That one glance answers the question the last lesson left hanging — which attributes are forced into every key, and which can never appear in one.

  • LHS-only — appears on some left-hand side, never on any right-hand side. Must sit in every candidate key. Nothing in the FDs produces it, so the only way to have it in your closure is to start holding it.
  • RHS-only — appears only on right-hand sides. Cannot sit in any candidate key. It is always producible from something else, so including it can never be minimal.
  • Both / neither — the optional middle. You may need some of these, and only here does any real searching happen.
LHS-onlyA, CMUST appear inevery candidate keyBoth sidesBOptional — try only ifLHS-only alone is not enoughRHS-onlyD, ECANNOT appear inany candidate keyExample split for R(A,B,C,D,E) under F = {A → B, BC → D, D → E}.
Three buckets. Two of them decide themselves; only the middle one needs searching.

The procedure

The classification turns into four mechanical steps.

  1. Classify every attribute as LHS-only, RHS-only, or both.
  2. Let K = the set of all LHS-only attributes. Compute K⁺.
  3. If K⁺ is every attribute, then K is the one and only candidate key. Stop — nothing smaller can work (you cannot drop a mandatory attribute), and nothing else can be minimal.
  4. Otherwise, add ONE “both” attribute at a time to K and recompute. If a single addition completes the closure, that set is a candidate key. If none does, try pairs, then triples — always keeping minimality by skipping any superset of a key you already found.

Most exam problems halt at step 3, or after a single one-attribute extension. The cost lives entirely in the “both” bucket; the smaller that bucket, the shorter the hunt.

How GATE asks this

  • NAT — “How many candidate keys does R have?” Run the procedure; count.
  • MCQ — “Which of the following is a candidate key of R?” For each option, ask two questions: is it a superkey, and is it minimal (drop each attribute, recompute the closure)?
  • MSQ — properties of candidate keys themselves: LHS-only inclusion, RHS-only exclusion, minimality, multiplicity.

Worked example

R(A, B, C, D, E) with F = {A → B, BC → D, D → E}. Find all candidate keys.

Step 1 — classify. Scan each attribute against the three FDs.

  • A: left of A → B. Never on any RHS. → LHS-only.
  • C: left of BC → D. Never on any RHS. → LHS-only.
  • B: left of BC → D; right of A → B. → both.
  • D: left of D → E; right of BC → D. → both.
  • E: only right of D → E. → RHS-only.

Step 2 — start from the mandatory set. The LHS-only attributes are A and C, so K = {A, C}.

Step 3 — compute K⁺, one firing at a time.

  1. Start closure = {A, C}.
  2. A → B: A is in, so add B{A, B, C}.
  3. BC → D: B and C are both in, so add D{A, B, C, D}.
  4. D → E: D is in, so add E{A, B, C, D, E}. Every attribute is in; stop.

{A, C}⁺ reaches everything, so {A, C} is a superkey. It holds both LHS-only attributes, and those are mandatory in any candidate key — so it cannot be shrunk. Therefore {A, C} is the unique candidate key.

No extensions are worth trying. Any other superkey would also have to contain {A, C}, which makes it a superset of the key we found — and a superset is never minimal.

In one breath

A candidate key is a minimal superkey: its closure spans the whole relation, and no proper subset already does. Sort the attributes by where they live in the FDs — LHS-only ones belong to every key, RHS-only ones to none, and the rest are the only attributes you ever search over. Start from the LHS-only set, grow its closure, and extend through the “both” bucket only if you must.

Practice

Quick check

0/6
Q1Recall — Which statements about candidate keys are TRUE? (select all that apply)select all that apply
Q2Trace — R(A,B,C,D) with F = {A → B, B → C, C → D}. How many candidate keys does R have?numerical answer — type a number
Q3Trace — R(A,B,C,D,E) with F = {AB → C, C → D, D → E, E → A}. How many candidate keys?numerical answer — type a number
Q4Apply — R(A,B,C) with F = {AB → C, C → A}. Which sets are candidate keys? (select all that apply)select all that apply
Q5Apply — R(A,B,C,D) with F = {A → BC, D → A}. Identify the LHS-only attribute, then state the size of the candidate key.numerical answer — type a number
Q6Create — An enrolment table Enrol(student, dept, course, grade) has FDs: student → dept; {student, course} → grade; dept → course. Which attribute is LHS-only, and so must appear in every candidate key?

A question to carry forward

You can now hand back, for any table, the full list of its candidate keys. That list quietly sorts every attribute into two camps: the prime attributes, which belong to at least one candidate key, and the non-prime ones, which belong to none. Hold onto that split — it is about to do real work.

Because a table can be technically correct and still feel badly built: the same department head copied onto every employee row, a customer’s whole order crammed into one cell, a fact you cannot record until some unrelated fact exists. Here is the thread onward: given the keys you just found and the prime/non-prime labels they imply, is there a precise ladder of “how clean is this design” that you can test a table against — and what exactly does each rung forbid?

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Practice this in an interview

All questions
Find all unique combinations of candidates that sum to a target, where each candidate may be used an unlimited number of times.

Use backtracking with a running total. At each step, try adding a candidate to the current path. If the total equals the target, record the path. If it exceeds the target, prune. Passing the same start index (not i+1) back into the recursion allows unlimited reuse of the same element.

How do you join tables on multiple keys, and why is the key order in a composite index important?

You combine conditions in the ON clause with AND to join on multiple columns, which is necessary when no single column is a unique identifier across both tables. For index performance, the most selective column — or the column used in equality predicates — should come first in a composite index.

What are 1NF, 2NF, and 3NF, and when would you intentionally denormalize?

1NF eliminates repeating groups and requires atomic column values. 2NF further removes partial dependencies on a composite key. 3NF removes transitive dependencies — every non-key column must depend on the key, the whole key, and nothing but the key. Denormalization trades update anomalies for read performance, and is appropriate when the read path dominates and write correctness can be enforced at the application layer or with materialized views.

What is the difference between a primary key and a foreign key, and what guarantees do they provide?

A primary key uniquely identifies each row in a table and implicitly creates a unique index; it cannot be NULL. A foreign key in a child table references the primary key of a parent table and enforces referential integrity — the database rejects inserts or updates that reference a non-existent parent row, and rejects parent deletes that would orphan child rows unless a cascade rule is defined.

Related lessons

Explore further

Skip to content