I'm currently working on a database with the following requirements: There are accounts of different types. They can have different payment plans depending on the type. The whole thing is like a hierarchy with 2 levels. For instance, if the account types were A and B, then the payment plans could be A1, A2, B1, and B2, where Ax would only be valid for account type A and so on.
So far I've got the following setup:
A table account_types with id and name. A table payment_plans with account_type_id and id, both of them are part of the PK. And a table accounts with type_id and plan_id. I guess it's obvious what references what.
My problem is this: accounts.type_id is a FK and accounts.type_id + accounts.plan_id is a composite FK. I don't know if this an optimal solution. The type_id is kind of redundant, since it's implicitly defined by the plan_id, but only because of the constraints in place in the payment_plans table. So what would be best practice here? I could get rid type_id entirely, but then it would take another join with the payment_plans table just to determine the type of an account.
Thanks for your input in advance. Suggestions involving a completely different structure are also welcome. ;-)
I would have these tables:
account_types:
id: PK
name
payment_plans
id: PK
account_type_id: FK to account_types
accounts
whatever columns an account needs
accounts2payment_plans
account_id: FK to accounts and part of PK
payment_plan_id: FK to payment_plans and part of PK
The reasoning behind this is the following:
Each account type can have multiple payment plans, therefore the payment_plans table needs to reference the account_type table. With this reference, the type of a payment plan is defined.
Each account can have multiple payment plans, but each payment plan can be used by multiple accounts, that's why the mapping table accounts2payment_plans is needed. Through the mapping from account to payment plans all account types of an account are implicitly defined.
Related
I am trying to simplify an application's database. In that database I have two tables let's say Patient and MedicalRecord. I know that two tables are said to be in One-to-One relationship iff that any given row from Table-A can have at most one row ine Table-B(It means there can be zero matchings).
But in my case, it is not at most, it is exactly. i.e., Every row in Patient should have exactly one row in MedicalRecord(no patient exist without a medical record).
Patient table has all personal details of the patient with his id as PK.
MedicalRecord talbe has details like his blood-group, haemoglobin, bp etc with his id as both PK and FK to the Patient.
My Question is, can I merge those two tables and create one table like,
PatientDetails : personal_details and blood-group, haemoglobin, bp etc
"bp" = "Blood pressure"? Then you must not combine the tables. Instead, it is 1:many -- each patient can have many sets of readings. It is very important to record and plot trends in the readings.
Put only truly constant values in the Patient -- name, birthdate (not age; compute that), sex, race (some races are more prone to certain diseases than others), not height/weight. Etc.
Sure, a patient may have a name change (marriage, legal action, etc), but that is an exception that does not affect the schema design, except to force you to use patient_id, not patient_name as a unique key.
Every patient must have a MedicalRecord? That is "business logic"; test it in the application; do not depend (in this case) on anything in the Database.
Both tables would have patient_id. Patients would have it as the PRIMARY KEY; MedicalRecord would haveINDEXed`. That's all it takes to have 1:many.
In situations where the tables are really 1:1 (optionally 1:0/1), I do recommend merging the table. (There are exceptions.)
If two tables have the same set of subrow values for a shared set of columns that is a superkey in both (SQL PRIMARY KEY or UNIQUE) then you can replace the two tables by their natural join. ("Natural join" is probably what you mean by "merge" but that is not a defined technical term.) Each original table will equal the projection of the join on that original's columns.
(1:1 means total on both sides, it does not mean 1:0-or-1, although most writing about cardinalities is sloppy & unclear.)
I'm trying to model a simple poll system, I have 4 tables
Election
id, title, description
Candidate
id, electionId, name
User
id, (other user details)...
Vote
userId, candidateId
There is a 1-n relation from Election to Candidate. If someone runs in multiple elections, they are listed as multiple candidates.
I'm having trouble figuring out how to constrain each user to one vote in each election at the database level. If I create an electionId column in Vote I create inconsistent or redundant data, but I can't think of any other way to constrain the data like that otherwise.
I feel like this has to be a common problem but I don't know what to call it so my last half an hour of searching hasn't been fruitful. What's the correct approach here?
You could change Candidate's PK to be a composite of electionId, name or at least make that combination a unique constraint in Candidate.
Then you would change Vote to be userId, electionId, name where the PK is userId, electionId and there is a FK pointing to Candidate's electionId, name which is now unique.
This means that userId and electionId are unique for the vote table and there is no redundancy left.
You can do this with your current schema by adding validation before the insert into Vote (in mysql this is done with a TRIGGER BEFORE INSERT). You'd select all votes by that particular user, joined with candidate on candidateId, and make sure none of the electionIds match the election Id of the candidate the vote is for.
This is completely normalized but expensive. Sometimes it's worth adding redundant fields for the sake of performance. I'd add electionId to Vote in this schema so that inserts don't need such an expensive validation.
Say I run an online business where you can order products from my website, and I have a database with two tables:
Table order with the fields order_number, customer_ID, address
Table customer with the fields customer_ID, first_name, last_name
To get a full, detailed 'report' of the order, I would perform a LEFT JOIN to concatenate data from the order table to include the customer's first and last names along with their address and order number.
My question is, how are these tables related? Are they at all? What would an entity relationship diagram look like? Separately they don't seem to interact and act more like lookup tables for each other.
An order would always have a customer, no? So it is not a left but inner join.
What links them is the customer_id. So your SQL is simply:
select o.order_number, o.customer_ID, o.address,
c.first_name, c.last_name
from orders o
inner join customer c on o.customer_ID = c.customer_ID;
Entity relationship:
Order Customer
Customer_Id 0...N >---+ 1 Customer_Id
... ...
This EF relation is from MS SQL Server's sample database Northwind. In that sample database, just like yours, there are Customers and Orders. Customers and Orders tables are related via the CustomerId fields in both tables (it is the primary key in Customers, and foreign key in Orders table). When you model that as an Entity relation than you have the above diagram. Customer entity have an "Orders" navigation property (via customerId) that points to a particular Customer's Orders. And Order entity have a navigation property that points to its Customer (again via CustomerId). The relation is 1 to 0 or many (1 - *), meaning a Customer might have 0 or more Orders.
When you do the join from Customer's side, you use a LEFT join "if you want to see all Customers regardless they have Order(s) or not" - 0 or more Order(s). If you want to see only those with Order(s) then you use an inner join.
When you do the join from Orders' side, then an Order must have a Customer so it can't be a LEFT join. It is an INNER join.
You can check the relation from both sides using the connecting CustomerId field.
You wouldn't have a separate table for "OrderId, CustomerId" as it is not many-to-many relation (it would be pure redundancy and would create normalization anomalies).
Hope it is more clear now.
In the entity-relationship model, we don't relate tables. Instead, we relate entities which are represented by their key values. In your example, the customer entity (represented by customer_ID) has a one-to-many relationship with the order entity (represented by order_number) and this relationship is recorded in the order table (where order_number is associated with customer_ID). If we were to strictly follow the ER model, we would record (order_number, customer_ID) (a relationship relation) in a separate table from (order_number, address) (an entity relation).
If there's a foreign key constraint on order.customer_ID referencing customer.customer_ID, that's a subset relation that ensures that every order's customer is a known customer. Thus, the relation between the tables and the relation between the entities is not the same thing.
The relational model allows us to relate (join) tables in any way we need. The obvious join for your example would be on the shared domain customer_ID, but I could just as easily find orders which contain a customer's last_name in its delivery address.
An ER diagram for your example could look like this:
My question is, how are these tables related? Are they at all? What
would an entity relationship diagram look like? Separately they don't
seem to interact and act more like lookup tables for each other.
When dealing with data modeling in an ER-Diagram, more in the conceptual model, we should never start thinking of tables, primary keys, foreign keys and stuff as this is for the later model to the conceptual model, the logical model.
By modeling entities in ER-Diagram, we must always recognize them by their attributes/properties. The entities become concrete when we can find properties in them. I feel a lack of context here, so I'll proceed with a guess:
If you need to persist products in your database, and you need to
save the attributes/properties of them, then we have a Products
entity.
If you need to persist clients/users in your database along with
their properties/attributes, then we have a Customers entity.
According to what you said, customers are able to purchase products. So, you have to relate these two entities in any way. With this in mind, stop and think about the following:
You need to persist purchases/orders.
Purchases/orders show which users bought which products.
By linking products and customers, what would we get? The purchasing/orders event, right?
We would then have two entities relating to each other forming the purchasing (or "orders", you name it) event. This event is formed by the need for the present business rules (your rules). You as modeler you need to persist the orders, and you know that products and customers relate in some way, so you can create a relationship between the two entities representing the orders event.
As has been well discussed in other answers, there is the need of separation of attributes here. If the field "address" is where a user lives, not where the product will be delivered, then this attribute must exist in the Customers entity.
If this field/attribute/property is the final location of delivery, it should remain in the relationship orders created between the two entities, customers and products.
Let's talk now about cardinality. If a customer can purchase/order more than one product, and the same product can be purchased by more than one user, then we have a N-N relationship here. I believe this is your case.
Based on everything that was said, we find the following conceptual model:
By decomposing this model, and developing the logic model, we would have:
Now, for what reason we end up with this kind of model?
Relations N-N allow the existence of properties/attributes (if needed), so we can have attributes/properties in the relation Orders, resulting in an ORDERS table with the fields shown. This table represents the purchases/orders made by users/customers.
And for what reason the existence of "Products from orders"?
We need to say what products were purchased in which purchases/orders, especially showing how many of the same type are acquired. In N-N relationships, some properties induces the appearance of new relations which become tables later. In such situations, it is the discretion of the modeler.
In "Products from orders" entity we have a composite primary key, represented by foreign keys.
With this type of model, you can see:
Which users made purchases/orders.
Which purchases/orders were made by which users.
Which products belong to which purchases/orders.
Which products have been acquired by which users.
How many products of a type were purchased/ordered.
Using the date field, you can find out how many purchases were made in periods:
Weeks.
Months.
Years.
Quarters.
Etc.
If you are interested, see also:
E-R diagram confusion
If you have any questions, please comment and I will answer.I hope I've helped a bit.
Cheers.
"Related" is a vague and confusing term. This is because "relationship" gets used in two different ways: as "association" (between values) and as "foreign key" (between tables).
You do not need to know anything about how tables are "related" by foreign keys or common columns in order to query. What matters is how values in a query's result rows are related/associated by the query. The important relationships/associations are (represented by) the tables.
From a relational perspective, there would be a foreign key from Order referencing Customer on customer_id.
A Chen-style ER diagram would have Order and Customer entity types (boxes) and an Orders relationship type (diamond) with participations (lines) from Orders to Order and to Customer. It would have a table for each type. This is an example of perfectly sensible relational design that the ER model, with its artificial and perverse distinction between entities and relationships, cannot capture. People will use a database design like yours to implement such an ER design, though. Even though the ER design isn't, then, the design.
--
When using a database, values are used to identify entities or as property names and magnitudes. Each base table holds the rows of values that participate in some relationship/association given by the DBA. Each query result holds the rows of values that participate in a relation/association that is a combination of conditions and the relationships/associations of the base tables it mentions. All you need to know to query is the relationships/associations of tables.
Order -- order ORDER_NUMBER is by customer CUSTOMER_ID to address ADDRESS
Customer -- customer CUSTOMER_ID is named FIRST_NAME LAST NAME
Order JOIN (Customer WHERE FIRST_NAME='Eddie')
-- order ORDER_NUMBER is by customer CUSTOMER_ID to address ADDRESS
AND customer CUSTOMER_ID is named FIRST_NAME LAST NAME
AND FIRST_NAME='Eddie'
Sometimes values for a list of columns in a row of one table must also appear as values for a list of columns in another table or that table. This is because if the listed values and others satisfy one table's relationship/association then the listed values and yet others will satisfy the other table's relationship/association.
/* IF there exist ORDER_ID & ADDRESS satisfying
order ORDER_NUMBER is by customer CUSTOMER_ID to address ADDRESS
THEN there exist FIRST_NAME & LAST_NAME satisfying
customer CUSTOMER_ID is named FIRST_NAME LAST_NAME
*/
FOREIGN KEY Order(customer_id) REFERENCES Customer(customer_id)
This means that those particular tables and column lists satisfy the (one and only) relationship/association "foreign key in this database". (And a database will have a meta-data table for its foreign key relationship/association.)
We say that "there is a foreign key" from the first table's list of columns to the second table's list of columns. There's only one foreign key relationship/association for the database. When there is a foreign key its tables and column lists satisfy this database's foreign key relationship. But a foreign key isn't a relationship/association. People call foreign keys "relationships", but they are not.
But foreign keys don't matter to querying! (Ditto for any other constraint.) A query's result holds rows whose values (entity & property info) are related/associated by that query's relationship/association, built from conditions and base table relationships/associations.
My UNF is
database(
manager_id,
manager_name,
{supplier_id,
supplier_name,
{order_id,
order_quantity}}
{purchase_id,
purchase_date}
Here manager_name, supplier_id, order_id and purchase_id are primary key.
During normalization there will be 1 table called purchase. Is it necessary to make manager_name as a foreign key?
How can I normalize these database?
This is a part of my college project on database. Normalization is really confusing.
First consider splitting things out by things that naturally go together. In this case you have manager information, supplier information, order information and purchase information. I personally would want to know the difference between an order and a purchase because that is not clear to me.
So you have at least four tables for those separate pieces of information (although depending on the other fields you might need, suppliers and managers could be in the same table with an additional field such as person_type to distinguish them, in this case you would want a lookup table to grab the valid person type values from). Then you need to see how these things relate to each other. Are they in a one to one relationship or a one-to many or a many to many relationship? In a one-to one relationship, you need the FK to also have a unique constraint of index to maintain the uniqueness. In a many to many you will need an additional junction table that contains both ids.
Otherwise in the simplest case the child table of purchase would have FKs to the manager, supplier. and order tables.
Manager name should under no circumstances be a primary key. Many people have the same name. Use Manager ID as the key because it is unique where name is not. In general I prefer to separate out the names into First, middle and last so that you can sort on last name easily. However in some cultures this doesn't work so well.
I had to implement the following into my database:
The activities that users engage in. Each activity can have a name with up to 80 characters, and only distinct activities should be stored. That is, if two different users like “Swimming”, then the activity “Swimming” should only be stored once as a string.
Which activities each individual user engages in. Note that a user can have more than one hobby!
So I have to implement tables for this purpose and I must also make any modifications to existing tables if and as required and implement any keys and foreign key relationships needed.
All this must be stored with minimal amount of storage, i.e., you must choose the appropriate data types from the MySQL manual. You may assume that new activities will be added frequently, that activities will almost never be removed, and that the total number of distinct activities may reach 100,000.
So I already have a 'User' table with 'user_id' as my primary key.
MY SOLUTION TO THIS:
Create a table called 'Activities' and have 'activity_id' as PK (mediumint(5) ) and 'activity' as storing hobbies (varchar(80)) then I can create another table called 'Link' and use the 'user_id' FK from user table and the 'activity_id' FK from the 'Activities' table to show user with the activities that they like to do.
Is my approach to this question right? Is there another way I can do this to make it more efficient?
How would I show if one user pursues more than one activity in the foreign key table 'Link'?
Your idea is the correct, and only(?) way.. it's called a many to many relationship.
Just to reiterate what you're proposing is that you'll have a user table, and this will have a userid, then an activity table with an activityid.
To form the relationship you'll have a 3rd table, which for performance sake doesn't require a primary key however you should index both columns (userid and activityid)
In your logic when someone enters an activity name, pull all records from the activity table, check whether entered value exists, if not add to table and get back the new activityid and then add an entry to the user_activity table linking the activityid to the userid.
If it already exists just add an entry linking that activity id to the userid.
So your approach is right, the final question just indicates you should google for 'many to many' relationships for some more info if needed.