Functional dependency and many-to-many relationships - database

I have these fields:
A book_id
B book_title
C book_isbn
D book_year
G reader_id
H reader_name
I reader_birthday
L reader_phone
M reader_email
N reader_registration_date
O loan_id
P loan_date_issued
S loan_date_for_return
T loan_date_returned
U author_id
V author_name
W category_id
X category_name
and these dependencies:
A->BCD
G->HILMN
O->AGPST
U->AV
W->AX
After all calculations I get this:
R1 = ABCD k1 = {A} Books
R2 = GHILMN k2 = {G} Readers
R3 = AGOPST k3 = {O} Loans
R4 = AUV k4 = {U} Authors
R5 = AWX k5 = {W} Category
R6 = OUW k6 = {OUW} {Don’t know}
But this is not good because table Book has a many to many relationship with table Category, and so do the Book and Author tables.
I'm stuck. I think I'm doing something wrong from the start and after that all goes wrong. Maybe you have some example for this.

Let's treat "category" as "cover" of a "book"-as-object or "copy" of a "book"-as-text, where a "book" is associated with some O values unique to it. Then W -> A makes more intuitive sense. (Other FDs seem unintuitive too.)
Universal relations
Every table (base or query result) has a predicate (statement template) that a row makes either into a true statement (and goes in the table) or a false statement (and stays out). We say the table represents the business relationship/association characterized by the predicate. A guess at a predicate here is:
book A titled B with isbn C published in year D
was borrowed by a reader G named H born on date I
with phone# L and email address M registered on date N
in loan O issued on date P due on date S
and either it was returned on date T or it is not yet returned and T=NULL
and it was written by author U named V
and the library has A in cover/copy W named X
You seem to be using the "universal relation" decomposition design/normalization technique. But this is only applicable if your one table satisfies the "universal relation assumption". Which is that all your situations can be described via the one predicate and its one table.
Eg: Suppose you can have books that have not been loaned or users that haven't borrowed. Then the example predicate/table above could not record them. So a decomposition wouldn't be able to record them. So you would instead start with a different predicate/table. (Typically multiple ones.)
Eg: If the last line was and A was borrowed in cover/copy W named X then the table could hold a different value in a given situation than before. But depending on the borrowing policy the table could satisfy the same set of FDs.
What is the predicate for this table? If it's not what you guessed, your expectations might not be met.
Your decomposition
Let's ignore the properties of entities.
-- O is G borrowing A by U with W
A book_id
G reader_id
O loan_id
U author_id
W cover/copy_id
O->AG
U->A
W->A
The only CK is OUW. Here is an obvious decomposition to BCNF. It agrees with your version.
-- O is G borrowing A by someone with some cover/copy
-- O is G borrowing A
Loan(O,G,A)
-- some loan is somebody borrowing A by U with some cover/copy
-- the book of U is A
The_book_of_author(U,A)
-- some loan is somebody borrowing A by someone with W
-- the book of W is A
The_book_of_cover/copy(W,A)
-- O is somebody borrowing some book by U with W
-- O is the borrowing of the book of U and W
Author_and_cover/copy(O,U,W)
The original relation is the join of the components:
-- O is G borrowing A
and the book of U is A
and the book of W is A
and O is the borrowing of the book of U and W
-- O is G borrowing A by U with W
Loan JOIN The_book_of_author JOIN The_book_of_cover/copy JOIN Author_and_cover/copy
this is not good because table Book has a many to many relationship with table Category, and so do the Book and Author tables
Unfortunately this is unintelligible. So I can't address what you mean to say is wrong.
Database design
If you generated this design yourself, you should be using some reference information modeling method. This will guide you to determine reasonable predicates/tables to record all the situations that can arise according to your business rules.
Predicates applied to what situations can arise determine what states can arise. Those valid states are described by constraints--FDs (functional dependencies), JDs (join dependencies), CKs (candidate keys), FKs (foreign keys) (aka "relationships" in a different sense than above), etc.
Part of a method is normalizing provisional tables to others. This uses FDs & JDs to decompose to an appropriate NF (normal form) via an appropriate algorithm. A good method always normalizes to 5NF. (Even if you denormalize it later for implementation reasons.)

Related

How to normalize the schema to BCNF

I am having some issues with normalization. I have a schema REPAYMENT which looks like this:
Now, from what I've gathered the functional dependencies that hold in the schema is
{borrower_id} --> {name, address, request_date, loan_amount}
{request_date} --> {repayment_date, loan_amount}
{loan_amount] --> {repayment_amount}
(correct me if I'm wrong?)
I'm supposed to normalise the schema to BCNF, but I'm a bit confused. Is the candidate key request_date and borrower_id?
It can be used to register information on the re- payments on micro loans. A borrower, his name and address, are identified with an unique borrower_id. Borrowers can have multiple loans at the same time, but each of those loans ( specified by loan_amount, repayment_date and repayment_amount) have a different re- quest date. Thus a loan can be identified with the borrower ID and the request date of the loan. The borrower can repay multiple (different) loans on the same date, but each loan can only be repaid once (on one date with one amount). There is a system which for each request date and amount of a loan determines the repayment date and amount to be repaid. The loan amount requested and the repaid amount are not the same since there is an interest rate that applies.
From the definition of candidate key:
In the relational model of databases, a candidate key of a relation is
a minimal superkey for that relation; that is, a set of attributes
such that:
The relation does not have two distinct tuples (i.e. rows or records in common database language) with the same values for these
attributes (which means that the set of attributes is a superkey)
There is no proper subset of these attributes for which (1) holds (which means that the set is minimal).
Now your question :
Is the candidate key request_date and borrower_id?
It is a superkey, but not minimal one. Here's how we compute the candidate key.
Which attribute occurs only on the left side, considering all the F . D's ?
ITS borrower_id.This means that it must be a part of every key of this given schema. Now let us compute its closure.
Because of {borrower_id} --> {name, address, request_date, loan_amount}:
closure(borrower_id) = borrower_id, name, address, request_date, loan_amount.
Because of {request_date} --> {repayment_date, loan_amount} and closure(borrower_id) has request_date, this means
closure(borrower_id) = borrower_id, name, address, request_date, loan_amount, repayment_date
And finally because of {loan_amount] --> {repayment_amount} and closure(borrower_id) has loan_amount, this means
closure(borrower_id) = borrower_id, name, address, request_date, loan_amount, repayment_date, repayment_amount
Because closure of borrower_id contains all the attributes, borrower_id is a key and since it is minimal, it is indeed the candidate key and the only one.
Now let us decompose the schema into BCNF. The algorithm is:
Given a schema R.
Compute keys for R.
Repeat until all relations are in BCNF.
Pick any R' having a F.D A --> B that violates BCNF.
Decompose R' into R1(A,B) and R2(A,Rest of attributes).
Compute F.D's for R1 and R2.
Compute keys for R1 and R2.
Since {request_date} --> {repayment_date, loan_amount} and request_date is not a key, it violates BCNF so we split schema into two relations:
R1(request_date,repayment_date,loan_amount)
R2(borrower_id,name,address,request_date,repayment_amount)
Clearly R1 is in BCNF. But R2 is NOT in BCNF , because we missed the following F.D. which is:
address --> name
and we know address is not the key, so we split the R2 further as:
R3(borrower_id,address,request_date,repayment_amount)
R4(address,name)
Now, clearly both R3 and R4 are in BCNF. Had we not split the R2 further, we end up storing the same combination of address and name for every loan the person takes, which is redundancy.

BCNF normalization

Could you please provide me with an article that gives an example of a DB design that is in 3NF but not in BCNF and then illustrates how to convert it to BCNF? All the articles that I saw which try to explain BCNF give examples of tables that are in 1NF and then convert them to BCNF. This doesn't let me see the difference between 3NF and BCNF.
Thanks in advance
An example with overlapping keys reveals the difference; having the predicate [P] and matching constraints (c x.y).
[P] Employee EMP, with email EMAIL, took course CRS in year YR.
(c 1.1) For each employee and course; that employee took that course at most once; it is possible that more than one employee took that course.
(c 1.2) For each each employee and course; that employee took that course in exactly one year.
(c 1.3) For each employee and year; it is possible that the employee took more than one course in that year.
(c 1.4) For each course and year; it is possible that more than one employee took that course in that year.
(c 2.1) For each employee, that employee has exactly one email.
(c 2.2) For each email, exactly one employee has that email.
(c 3.1) For each email and course; employee with that email took that course at most once; it is possible that more than one employee with that email took that course.
(c 3.2) For each each email and course; employee with that email took that course in exactly one year.
(c 3.3) For each email and year; it is possible that employee with that email took more than one course in that year.
(c 3.4) For each course and year; it is possible that more than one employee with specific email took that course in that year.
Note how verbalizing constraints intuitively reveals the problem. See how constraints c 3.x match (repeat) c1.x due to c 2.x.
R {EMP, EMAIL, CRS, YR}
KEY {EMP, CRS}
KEY {EMAIL, CRS}
The FDs for this are
FD {EMP, CRS} --> {YR}
FD {EMAIL, CRS} --> {YR}
FD {EMP} --> {EMAIL}
FD {EMAIL} --> {EMP}
So, considering each one of these as FD X --> Y it holds that either,
X is a superkey,
Y is a subkey.
Therefore the R is in the 3rd NF.
For BCNF, the requirement is that for any nontrivial FD X --> Y in R, X is a superkey.
Here is a check-list for 2NF to BCNF
---------------------------------------
For each nontrivial | NF
FD X --> Y |
at least one holds | 2nd 3rd BCNF
---------------------------------------
X is a superkey ✔ ✔ ✔
Y is a subkey ✔ ✔
X is not a subkey ✔
---------------------------------------
FD X --> Y is trivial iff Y ⊆ X
Now we could decompose R into:
{EMP, EMAIL} {EMP, CRS, YR}
OR
{EMP, EMAIL} {EMAIL, CRS, YR}
which eliminates those two FDs to subkeys.
And finally, note that after decomposition into {EMP, EMAIL} {EMP, CRS, YR} or into {EMP, EMAIL} {EMAIL, CRS, YR} these tables are now all in 5NF -- actually in 6NF, but that's not important now. It is important to observe that it is possible to get into 5NF -- and hence into: (4, BCNF, ..., 1) -- just by using logic, verbalizing predicate and constraints. In other words, for a developer:
your tables can be in high NF even if you have no idea what all this terminology means.

Determining Super Key

According to Wikipedia
Today's Court Bookings
Each row in the table represents a court booking at a tennis club that has one hard court (Court 1) and one grass court (Court 2)
A booking is defined by its Court and the period for which the Court is reserved
Additionally, each booking has a Rate Type associated with it. There are four distinct rate types:
SAVER, for Court 1 bookings made by members
STANDARD, for Court 1 bookings made by non-members
PREMIUM-A, for Court 2 bookings made by members
PREMIUM-B, for Court 2 bookings made by non-members
The table's superkeys are:
S1 = {Court, Start Time}
S2 = {Court, End Time}
S3 = {Rate Type, Start Time}
S4 = {Rate Type, End Time}
S5 = {Court, Start Time, End Time}
S6 = {Rate Type, Start Time, End Time}
S7 = {Court, Rate Type, Start Time}
S8 = {Court, Rate Type, End Time}
ST = {Court, Rate Type, Start Time, End Time}, the trivial superkey
Note that even though in the above table Start Time and End Time
attributes have no duplicate values for each of them, we still have to
admit that in some other days two different bookings on court 1 and
court 2 could start at the same time or end at the same time. This is
the reason why {Start Time} and {End Time} cannot be considered as the
table's superkeys.
How is S1 = {Court, Start Time}, a super key?
Say on day 1, a member books court 1 from 11:00 to 12:00, and on day 2, a non member books court 1 from 11:00 to 12:00.
the records in the table would be
{1,11:00,12:00, SAVER} and {1,11:00,12:00, STANDARD}
Clearly S1 = {Court, Start Time}, is not superkey. Or am I wrong?
This example is a poor choice because to understand what the table is supposed to hold involves unstated, although common sense, assumptions. It expects you to see that the table is only for one day--"Today"--and infer that on any day there will be no overlapping bookings. Ie no start-end time period for a court overlaps another one for the same court. (The text mentions different days when they mean different table values; but it doesn't matter to the example whether different values have to be on different days.)
It is also a poor choice for 3NF vs BCNF in particular. Of course it is subject to certain FDs (functional dependencies) and their associated JDs (join dependencies) relevant to 3NF vs BCNF. But the non-overlap of bookings is a separate constraint irrelevant to 3NF vs BCNF.
Say on day 1, a member books court 1 from 11:00 to 12:00, and on day 2, a non member books court 1 from 11:00 to 12:00.
When we say that a table value "satisfies" a constraint (eg FD) or "is subject to" a constraint or "has" a constraint or that a constraint "holds in" a table value we mean that the value makes the constraint true. When we say this about a table variable (base table) we mean that it is so for the variable's value in every database state. For this table, describing the current booking situation for "Today", any particular booking situation will be about one day--Today. So the kind of overlapping involving different days in your quote is not relevant to the constraints. Similarly each table value from different times in the same day will satisfy the constraints itself regardless of how the bookings have changed.
Under those circumstances, for any state of the table the four specified sets of columns are CKs (candidate keys):
S1 = {Court, Start Time}
S2 = {Court, End Time}
S3 = {Rate Type, Start Time}
S4 = {Rate Type, End Time}
Because bookings don't overlap, a subrow value for each of these column sets is unique under those columns. So they are superkeys. Since that's true for no smaller subsets of each, they are CKs. Since its true for no other column sets, there are not other CKs. Since every superset of a superkey is a superkey, the other listed sets are the other (non-CK) superkeys.
PS There are a few sections on that entry's talk page about the Tennis/Booking example and confusions on the page. The page has other poor examples. Eg it restructures the non-BCNF 3NF design to a BCNF design, but not by standard lossless decomposition to projections of the original (that join back to it). (It introduces a new column.) Eg it then also talks about preserving dependencies but that only makes sense when decomposing to projections of the original.

Should I create two table to store specific information of an object?

I have some table:
Course: contain info about course, one course has many topics.
Topic: contain info about topic, one topic belongs to one course and one topic has many questions.
Question: contain info about question, one question belongs to one topic.
GeneralExam: Contain info about the exam of a course, one general exam belongs to one course.
GeneralQuestion: Contain set questions of General Exam.
This is columns of two table:
GeneralExam: name, description, semester, duration, user_id, course_id, used (boolean), number_question
GeneralQuestion: general_exam_id, question_id
The questions will be get for GeneralExam is random. It means I will get random questions depend on specific number of question of each topic.
Now I want to know specific information of an general exam, like the number of questions of each topic in course which was made a general exam. Currently, I think I will create a new table to store that info, something like:
New table: general_exam_id, topic_id, number_question
But I don't know if this is the best way to do it, or maybe in this case, has other ways or patterns to solve. Because If I create that New table, when I make a change in GeneralExam table(ex: change set questions), I will need to update 3 table: GeneralExam, GeneralQuestion, New table. I don't sure it is the good way.
So I want to ask, should I create new table to store that information (number of questions of each topic in course of a general exam),
Or should I need to make some changes in table GeneralQuestion for store info of general exam better, and what changes I should do? Thanks for any suggestions and advices.
We are trying to say, that is not required to create a new extra table. You want to manage your schema efficiently with mimimal touches to tables.
Design Rules:
One should not confuse the numbered topics in a particular course book to Topic table's ID numbers. Course doesn't necessarily have to be belonged to an Exam. It's the Exam who must belong to a Course. You have gotten your design so far correct. I assume you are storing all Questions for an Exam in GeneralQuestion table which acts like sort of a question bank of past Exams (including the schedule Exam in the near future which only gives access to the Exam moderators).
Makes more sense to rename your GeneralQuestions table into ExamsQuestions. With this bank your design makes two virtual question types: Exam questions from the bank and questions from Question table where Exam questions are referencing to your Question table. So that gives your the required referencial key to Exam question bank. In my opinion it is a history table. It seems like, your final table that you are not sure should ideally be just a stored query providing real time data.
Main question : Are you planning to store each past/scheduled-future Exam's questions? You say Yes. Hence,
Date becomes very crucial column in your Exam table according to the design I have provided. You need both Date & Course ID in Exam table.
Following is how I would suggest the table schema.
Reference on SQLFiddle
tblCourse
ID, Course
ID NAME
b105 biology 1st year
c323 chemistry 1st year
e120 english 1st year
m122 maths 1st year
m250 maths 2nd year
p302 physics 3rd year
tblTopic : Although ID is indexing, the CID is what recognizes the Topic's Parent (the Course)
ID, CID, Topic
ID CID NAME
t1 m122 Algebra
t2 m122 Probability
t3 e120 Essay Writing
t4 p302 Optics
t5 b105 liver system
t6 b105 neural system
t7 p302 mechanics
tblQuestion : Although ID is indexing, the TID is what recognizes the Question's Parent (the topic)
ID, TID, Question
tblExam : Although ID is indexing, the CID is what recognizes the Question's Parent (the course)
ID, CID, Exam, Date
ID TID QUESTION
q1 t2 x
q10 t7 p
q11 t4 n
q12 t6 i
q13 t7 r
q14 t6 k
q2 t1 y
q3 t1 z
q4 t2 a
q5 t2 v
q6 t6 s
q7 t6 h
q8 t1 l
q9 t2 g
tblExamsQuestions : Foreign Keys : Exam ID, Question ID
ID, QID
ID CID EXAM DATE
e1 b105 1st Year Biology Main Stream June, 08 2012
e2 m122 1st Year Maths Elective December, 20 2011
e3 b105 1st Year Biology Main Stream February, 10 2012
Application:
Somebody wants to get last year's Exam Questions for 1st Year Maths Course. How do you query that? If Exam ID is are on auto increment then it's very hard to know what which id is what exam. So here you could be able to search questiosn for a particular course exam only with course id and date the exam held. That should do the job -> Unless same course exams held multiple times on the same day. Then you can save your data by Time as well. You can remove Date, Time as long as you change your Exam table design to query by Exam ID where the ID is a proper exam ID not just 1, 2, 3, ...
Course ID = m122
Date = Last Year/Month/Date
These are the most logical/important details which will work as a COMPOSITE SEARCH KEY you need to find the Exam ID from Exam table and use that in ExamsQuestions bank to pull the Exam questions.
select * from question
where id in (
select eq.qid from examsquestions eq
inner join exam e
on e.id = eq.id
where e.date = '2011-12-20'
and e.cid = 'm122');
ID TID QUESTION
q1 t2 x
q5 t2 v
q7 t6 h
By the way since you are choosing questions randomly for an Exam - I would be so worried that if I have to take that Exam. Because the risk of getting all questions from one topic is pretty wide. Anyway that's a side issue which I hope you have a unbiased yet FAIR mechanism to generate Exam from all topics for a course ;)
Let me if you have further doubts. Anyone please throw some light to improve ideas for better solutions.
PS: Sorry for the late reply.
If the information you want can be queried from the current data, in general you should not store it in another table. The reason is: every time you add/remove rows from other tables, you'd have to update this one as well. It's easy to create data inconsistencies that way.
For your example (number of questions of a given topic in an exam), you can easily retrieve that info using aggregation:
select q.topic_id, count(gq.question_id)
from topic t join question q on t.id = q.topic_id
join general_question gq on q.id = gq.question_id
where gq.general_exam_id = 10
group by q.topic_ic;
OTOH if the data you want to store is not deduceable from the rest of the data, then yes, it's better to store it where it makes sense - if it's specific to the pair (exam, topic), then on a table that has those two values as its candidate key (i.e. exactly the way you suggested in your question). Whether to create a new table or add those columns in an existing one (with the correct candidate key, of course), it's your choice, I don't have any arguments for or against doing so.

Identifying Functional Dependencies II

Here is an example which should clear things up for the last post.
hireDate & carReg are the primary keys. Are there extra functional dependencies (FDs) other than the ones I have identified
below? Modifications also welcome:
fd1 carReg -> make, model, outletNo, outletLoc
fd2 custNo -> custName
fd3 outletNo -> outletLoc
fd4 model -> make (only if we assume a model name is unique to a make)
fd5 carReg, hireDate -> make, model, custNo, custName, outletNo, outletLoc
I'm not sure if the above are correct and I am sure there are more.
Based on Mike Sherrill Cat Recall's answer... My question is this: How is custName -> custNo a valid FD? For the above relation, sure, a customer name maps onto exactly one customer number, but by intuition, we know more than one J SMith could be added to the table. If this is the case, this FD is void as it forms a 1..* relationship. Can we really say that custName -> custNo knowing this fact? Do we merely base FDs on the sample data? Or do we take into account the possible values that can be added?
At a glance . . .
custName -> custNo
model -> make
outletLoc -> outletNo
carReg, custNo -> hireDate
carReg, custName -> hireDate
And I'm sure there are others. The sample data isn't representative, and that's a problem when you try to determine functional dependencies from data. Let's say your sample data had only one row.
carReg hireDate make model custNo custName outletNo outletLoc
--
MS34 0GD 14/5/03 Ford Focus C100 Smith, J 01 Bearsden
FDs answer the question, "Given one value for 'x', do I know one and only one value for 'y'?" Based on that one-row set of sample data, every attribute determines every other attribute. custNo determines hireDate. hireDate determines outletLoc. custName determines model.
When sample data isn't representative, it's easy to turn up FDs that aren't valid. You need more representative sample data to weed out some invalid functional dependencies.
custName -> custNo isn't valid ('C101', 'Hen, P')
carReg, custNo -> hireDate isn't valid ('MS34 0GD', 'C100', '15/7/04')
carReg, custName -> hireDate isn't valid ('MS34 0GD', 'Hen, P', '15/8/03')
You can investigate functional dependencies in sample data by using SQL.
create table reg (
CarReg char(8) not null,
hireDate date not null,
Make varchar(10) not null,
model varchar(10) not null,
custNo char(4) not null,
custName varchar(10) not null,
outletNo char(2) not null,
outletLoc varchar(15) not null
);
insert into reg values
('MS34 OGD', '2003-05-14', 'Ford', 'Focus', 'C100', 'Smith, J', '01', 'Bearsden'),
('MS34 OGD', '2003-05-15', 'Ford', 'Focus', 'C201', 'Hen, P', '01', 'Bearsden'),
('NS34 TPR', '2003-05-16', 'Nissan', 'Sunny', 'C100', 'Smith, J', '01', 'Bearsden'),
('MH34 BRP', '2003-05-14', 'Ford', 'Ka', 'C313', 'Blatt, O', '02', 'Kelvinbridge'),
('MH34 BRP', '2003-05-20', 'Ford', 'Ka', 'C100', 'Smith, J', '02', 'Kelvinbridge'),
('MD51 OPQ', '2003-05-20', 'Nissan', 'Sunny', 'C295', 'Pen, T', '02', 'Kelvinbridge');
Does model determine make?
select distinct model
from reg
order by model;
model
--
Focus
Ka
Sunny
Three distinct models . . .
select model, make
from reg
group by model, make
order by model;
model make
--
Focus Ford
Ka Ford
Sunny Nissan
Yup. One make for each model. Based on the sample data, model -> make.
Does carReg, custName -> hireDate?
select distinct carReg, custName
from reg
order by custName;
carReg
--
MH34 BRP Blatt, O
MS34 OGD Hen, P
MD51 OPQ Pen, T
MS34 OGD Smith, J
NS34 TPR Smith, J
MH34 BRP Smith, J
Six distinct combinations of carReg and custName.
select carReg, custName, hireDate
from reg
group by carReg, custName, hireDate
order by custName;
carReg custName hireDate
--
MH34 BRP Blatt, O 2003-05-14
MS34 OGD Hen, P 2003-05-15
MD51 OPQ Pen, T 2003-05-20
MH34 BRP Smith, J 2003-05-20
NS34 TPR Smith, J 2003-05-16
MS34 OGD Smith, J 2003-05-14
Yup. One hireDate for each combination of carReg and custName. So based on the sample data, {carReg, custName} -> hireDate.
Well, since you asked for a second opinion, I'll give you one.
The second opinion is that the first (CatCall's) is entirely correct.
Sample data do not suffice to identify/determine functional dependencies in the data. What is needed to identify/determine functional dependencies in the data, are user requirements, descriptions/definitions of the business environment the database is intended to support, ...
Only your users can tell you, one way or another, what functional dependencies apply. (Don't interpret this as meaning that you should be telling your users that they should be telling you "what the applicable FDs are", because your users will typically not know what the term means. However, what the applicable FDs are, can still be derived from nothing else than the business specs the user provides you with.)
(PS sample data may on the contrary indeed suffice to demonstrate that a certain given FD certainly will NOT apply. But that's not your question.)
A FD (functional dependency) expresses a certain property of a relation value or variable. We can say that it holds for or doesn't hold for (is satisfied by or isn't satisfied by) (is true of or is not true of) a given relation value. When we say it holds or doesn't hold for a relation variable we mean it holds or doesn't hold for every possible value for the variable that can arise in an application.
Also if we are given a value and we are told that the FDs it satisfies are the FDs that a variable that could hold it satisfies then by that assumption the variable's FDs are the value's FDs. (This is sometimes called "representative data" for the variable.) But if we are just given a value that might arise for a variable then we only know that
the FDs that don't hold in the value also don't in the variable
the trivial FDs of both hold
(the ones of the form S -> subset of S)
(the ones that must hold regardless of the value, based only on the attributes)
(which must be the same for the value & the variable)
From my answer to What did I do wrong? (Find FD from table):
We say that a FD (functional dependency) expression S -> T has a
"determinant" set of attributes S and a "determined" set of
attributes T. It says that a given subtuple value for S appears in a
given relation value or variable/schema always with the same subtuple
value for T. For S -> {A} we can say S -> A. For {A} -> T we can say A
-> T.
Given a relation, we say that a FD "holds in" it or "is satisfied by"
it or "is true" in it or (sloppily) "is in" it or (sloppily) it "has"
a FD when what the FD says is true about it. Every FD that can be
expressed using attributes of a relation value/variable/schema will
either hold or not hold.
We can find all the FDs S -> T that hold in a relation by checking
every subset of the set of attributes as S with every subset of
attributes as T. There are also algorithms. FDs where S is a superset
of T must hold and are called "trivial".
We can find all the FDs S -> A that hold in a relation by checking
every subset of the set of attributes as S with every attribute as A.
There are also algorithms. (Then to find all FDs that hold: FDs S ->
{} hold trivially & whether S -> T for T with multiple elements can be
found from the FDs S -> A.)
Here are some shortcuts: A set determines itself. If S -> T then every
superset of S determines every subset of T. If S doesn't determine T
then no subset of S determines any superset of T. If a set has a
different subtuple of values in every tuple (ie it is "unique", ie it
is a superkey) (including if it is a candidate key) then it determines
every set. {} -> T when/iff every tuple has the same T subtuple value.
Given some FDs that hold, Armstrong's axioms generate all FDs that
must also hold. The latter is called the "closure" of the former. A
set of FDs that generates a certain closure is called a "cover". A
cover is "minimal" or "irreducible" when removing any FD from it gives
a set that is not a cover. A minimal/irreducible cover with every
determinant unique is "canonical".
Usually we are not asked to give a closure for all FDs that hold in a
schema, we are asked to give a canonical cover for them. In general if
we only know some FDs that hold in a schema then we don't know that
its closure is all the FDs that hold.
Assuming not every possible table value for a table variable is given, determining FDs for a table variable requires its meaning/predicate & the business rules to be given.
See my answer to Identifying functional dependencies (FDs).
Here's my attempt at relationships:

Resources