In relational schema design, what does it mean to say that a functional dependency X -> Y holds on a table, and how do you decide whether one actually holds for a given set of columns?
answer
- Same X implies same Y
- Constraint on all legal states, not on current rows
- Data can falsify, never verify
- Direction matters: X->Y is not Y->X
- Trivial when right side is inside left side
basics
~20 sX -> Y means any two rows that agree on every column of X must also agree on Y: X determines Y. It is a rule about all legal data, so sample rows can disprove it but never prove it.
solid answer
~50 sA functional dependency `X -> Y` is a constraint on a relation: for any two rows r1 and r2, if `r1[X] = r2[X]` then `r1[Y] = r2[Y]`. X and Y are *sets* of columns, so either side may be composite, e.g. `(order_id, line_no) -> product_id`. The crucial point is where an FD comes from. It asserts something about **every legal state** of the table and is derived from the semantics of the business domain, not from the rows currently stored. `zip_code -> city` holds under some postal systems and fails under others; only a domain rule settles it. Querying the data can therefore **falsify** a candidate FD by finding a counterexample, but never confirm it - today's rows may simply not contain the exception yet. FDs are directional: `X -> Y` does not imply `Y -> X`. An FD whose right side is contained in its left side is *trivial* and carries no information. Keys, decomposition and every normal form are defined in terms of FDs.
code
sql · 4 linesSELECT country, count(DISTINCT currency) AS distinct_values
FROM accounts
GROUP BY country
HAVING count(DISTINCT currency) > 1;go deeper
State the definition precisely - equal X values force equal Y values - and give one concrete example plus one counterexample in each direction.
Add that FDs are domain constraints over all legal states, that data can only falsify them, and that both sides may be composite.
Emphasise sourcing FDs from business rules and time-varying traps like product_id -> price, and mention that declared constraints are what actually enforce them.
Frame the FD set as the design artefact everything else derives from: wrong FDs produce wrong keys, unsafe decompositions and silent data loss, so their provenance and review matter more than the mechanics.
## The definition A relation has a set of attributes (columns). A **functional dependency** `X -> Y`, where X and Y are sets of attributes, asserts: > For any two rows r1 and r2 that may legally exist in the relation at the same time, if r1 and r2 are equal on every attribute of X, then they are equal on every attribute of Y. Read it as "X determines Y" or "Y is functionally dependent on X". It is exactly the mathematical notion of a function: one X value maps to at most one Y value, though many X values may map to the same Y value. ## Both sides are sets The left side is frequently composite. In an order-line table, neither `order_id` nor `line_no` alone determines `quantity`, but together they do: `(order_id, line_no) -> quantity`. The right side can also be a set, and `X -> {A, B}` is exactly equivalent to `X -> A` together with `X -> B`, so people usually write FDs with a single attribute on the right. ## Trivial vs non-trivial If Y is a subset of X the dependency holds automatically - `(a, b) -> a` is true of any data whatsoever. Such **trivial** FDs are true but useless; the interesting ones are non-trivial, where Y contains at least one attribute outside X. ## FDs come from the domain, not from the rows This is the single most-missed point. An FD is a *constraint*, a claim about all possible future states. Suppose a `users` table currently happens to have a distinct `phone` for every `country`. Running `SELECT country FROM users GROUP BY country HAVING count(DISTINCT phone) > 1` returns nothing - but that does not make `country -> phone` a real dependency; it is an accident of a small dataset. So data can only be used **negatively**. A query that finds two rows with the same X and different Y is a proof that the FD does *not* hold. The absence of such rows is weak evidence at best. Establishing an FD requires a business rule: "a person has exactly one national ID", "an invoice belongs to exactly one customer", "a product code determines its unit of measure". A closely related trap is **time**. Many apparent dependencies hold only at a point in time. `product_id -> price` is false in a table that stores historical order lines, because the price changes over the life of the product; it is true only if the column means "the price at the moment this row was written", which is a different attribute. ## Direction matters `employee_id -> email` says an employee has one email. It does not say an email belongs to one employee; that is the separate FD `email -> employee_id`. Both may hold, one may hold, or neither. Candidates who treat FDs as symmetric get key derivation wrong immediately. ## What an FD is not - **Not a foreign key.** A foreign key is a referential constraint between two tables; an FD is a constraint among columns within one relation. - **Not a correlation.** Statistical association is irrelevant; the FD is exact and absolute, with no tolerance for exceptions. - **Not implementation.** A `UNIQUE` constraint is one way an engine can enforce the FD `X -> everything`, but the FD exists in the design whether or not anyone declared a constraint. ## Why they matter Everything in schema theory is built on top of FDs. A **superkey** is a set X such that X determines all attributes. Decomposition rules test which FDs survive a split. The normal forms are stated purely as restrictions on which non-trivial FDs a relation is allowed to contain. Query optimizers use them too: knowing `X -> Y` lets a planner drop a redundant grouping column or prove that a join preserves row counts. Getting the FD set right is therefore the real work; the mechanical parts of normalization follow from it.
- Can you prove that a functional dependency holds by querying the table?No. A query can only find counterexamples - two rows sharing an X value but differing on Y - which disproves the dependency. Finding none merely means the current data is consistent with it; the exception may arrive tomorrow. Confirming an FD requires a rule from the business domain, and ideally a declared constraint that stops violations from ever being written.
- Does X -> Y imply Y -> X?No, functional dependencies are directional. `employee_id -> department` can hold while `department -> employee_id` clearly fails, since a department has many employees. When both directions hold the two attribute sets determine each other and are said to be equivalent, which usually means both are candidate keys of the relation.
- What is a trivial functional dependency and why do we exclude it?An FD `X -> Y` is trivial when Y is a subset of X, for example `(a, b) -> b`. It is satisfied by every possible relation, so it constrains nothing and adds no information about the design. Normal-form definitions explicitly say "for every non-trivial FD" precisely so these vacuous cases do not make every table look violated.
Think of a vending machine: pressing the same button always dispenses the same item. The button code determines the product. Two different buttons may dispense the same product, which is why the reverse direction need not hold.
saying these in an interview costs you the question
- Claiming an FD is proven because the current data satisfies it
- Treating FDs as symmetric, so X -> Y is assumed to give Y -> X
- Confusing a functional dependency with a foreign key between tables
- Describing an FD as a statistical correlation or a 'usually true' relationship
- Assuming the left side of an FD must be the primary key