I have a system that lets members rent equipment and the system should have a history of each item that was rented and by who. The system should also track who has what equipment rented/checked out and should also sort the equipment by type, status, name, etc. Lastly it should also send out notification email on equipment that are overdue.
I'm trying to understand the relationships and how I should model this. As of now my current tables and thinking is something like this:
Member Table:
Id (PK)
MemberId
FirstName
LastName
Email
EquipmentItem Table:
Id (PK)
EquipmentName
EquipmentType (FK)
EquipmentStatus (FK)
TotalQuantity
RemainingQuantity
EquipmentStatus Table:
Id (PK)
StatusName
EquipmentType Table:
Id (PK)
TypeName
EquipmentRentalHistory Table:
Id (PK)
MemberId (FK)
EquipmentId (FK)
CheckOutDate
ReturnedDate
1) I want to know the relationships between these would the rental history be a many to many relationship between the Member table and EquipmentItem table?
2) Would EquipmentItem table have a one to many relationship between the status and type, the way I see it is EquipmentItems can have many statuses or types but each status or each type can only belong to one EquipmentItem.
3) Does it make sense to have a quantity field in the EquipmentItem, I used to work in a grocery store so I'm basing the logic on barcodes where same products would usually have the same barcode e.g. (Cheetos Puff chips) all Cheetos Puff chips would have the same barcode but would have a quantity value on it. Or would it be better to have each item unique regardless if it's the same product/model?
My logic would be:
member rents out item
system logs it into the history table
system then checks how many of the same item has been checked out so far, if say we have total quantity of 4 on that item and 3 members has checked it out
we update the remaining quantity field to the difference so in this case to 1
system can then track who has what checked out by returning all records with a returned date of null
system will then check all records with a returned date of null and then do a date range on the checked out date to determine if the equipment is overdue
send notification to member emails associated with said records from step 6
I would just like some help better understanding the relationship between these and if I have modelled my tables correctly, if not, it would be great if someone can point me in the right direction of improving upon this.
To answer your questions
With respect to modelling in an ERD, I don't think that qualifies as a many-to-many relationship, but rather, EquipmentRentalHistory is its own entity that has a many-to-many relationship with both Member and EquipmentItem.
A many-to-many would be more like, "a Member has access to 0...n EquipmentItems, and each EquipmentItem can be accessed by 0...n Members".
I would disagree that they are a one-to-many relationships.
An oxygen tank and a pair of flippers can both be classified as 'Scuba Gear' and have the status 'Checked Out'.
You could have multiple 'Scuba Gear' tags and assign each unique 'Scuba Gear' tag to its very own EquipmentItem, but then you'll just be creating new tags for every new EquipmentItem, rather than reusing existing ones.
That really depends on whether you want to identify exactly which piece of equipment a member rented (maybe something is damaged you can track down everyone who rented that specific one?). If you do differentiate, then every item will just be its own row. You should also add a new column as an external identifier, but there would be no need to keep a tally.
If it's all the same to you, then I would only keep the total but not the available. If you kept the available column, then you would constantly have to update it whenever something is logged in EquipmentRentalHistory. This would be annoying if the tables fall out of sync. You could just query EquipmentRentalHistory for the Id of the equipment, and count up the entries where returnedDate IS NULL for the number of equipment that is currently in use
Additional Note
It might be good to have a 'due date' column in the rental history rather than hard code the date calculation in case you want to varying due dates. This way you can also grant extensions.
Related
I want to create a database following the following specifications:
A well known bicycle company stores its data in a special database.
Company has customers and
products.
All customers have a unique customer_id.
Customers are categorized as foreign customers or domestic customers. A customer must
be foreign or domestic, and can not belong to both of the categories at the same time.
Foreign customers are identified by their unique id, currency, company name and address
composed of city state and zipcode.
Domestic customers are identified by their unique id, name and address. Domestic
customers may have more than one address information.
Products are identified by unique product_id, model, type and price.
Only two type of products are produced in this company. These product types are Bike and
Mountain Bike.
Each bike has color and cycle attributes.
Each mountain bike has cycling team attribute.
A product may belong to at least one of this types. Moreover it may belong to both of them
at the same time.
Customers may request products. And a product may be requested by more than one
customer, also it may not be requested by any customer at all.
When a product is requested or ordered by a customer; request id, request type and request
content information is stored.
I asked about the composite key address and I got 2 possible choices right now: Create a table for address or create city, state and zipcode keys and add a constraint named address. However, it says that a domestic customer may have more than one address information. I don't know how to do that.
I have two tables. 'Products' and 'Discounts'.
Then I create a joining table 'discount_product' for Many-to-many relationship. So far so good.
Now if I want a discount to belong to ALL of the products I have to make insertions into the joining table for as many products I have. That means that having 10000+ products I'll have to insert 10000+ rows for one discount into the joining table? And that's only for one discount! What if I have 1000?
That's compelling me into returning to the old (wrong) way of doing it when I just have a column 'product_ids' in the 'Discounts' table with something like this '1|2|4|7|23|...' (or '*' for 'belongs to all') and then make a small piece of PHP code to check if discount belongs to all or to some products. I know it's wrong way of doing it. So is there a better way to make this properly?
Structure:
**products**
id
description
price
**discounts**
id
procent
value
**discount_product**
product_id
discount_id
I propose to try to change some business logic.
If the discount is not in the discount_product then this means that it applies to all products.
If the discount is in the discount_product then it means that it works only for a certain product.
If you need to ensure that the discount is not applied to any product, add the field is_active in discounts.
It's just my thoughts.
I believe that sometimes it is useful to denormalize the database because of optimization, and I would do as you suggested with the product_ids field.
I'm attempting to create a relational database for a tech company who perform sales, leases and offer support. I must store data for each of these, but the items that they are selling have the potential to be hardware or software based. This means that for sales that relate to hardware, a delivery address must be stored, whereas this would not be required for software.
So far I have attempted modelling this conceptually and have decided to have tables "sales", "leasing" and "support". Then linking to this, I have "product", which will have an id and generic product information, linking to separate "hardware" and "software" tables.
Part of the conceptual model
My concern is that if the product is hardware-based, the sales/leasing/support table's attributes would need to be different to allow for an address entry.
This has left me really stuck with how to model this part, and I would really appreciate any input that anyone could give.
Thanks in advance!
I think you want to look into normalization more and see if this answers your question. I think you should focus on one problem point and really expand on it with data/explanation/ERD to show us what data is available in what scenarios.
Let me expand some assumptions on what you said:
This means that for sales that relate to hardware, a delivery address must be stored, whereas this would not be required for software.
So let's say a PRODUCT is SOLD. The "Sale" is an entity that holds information such as
Date of sale
Price sold
Qty
Then, if the product is hardware or software, extra data is stored. Let's say you only store extra details for hardware - namely, a delivery address:
Delivery address (stored for hardware sales only)
So it sounds like "Sale_Hardware" is a sub-entity of "Sale".
PRODUCT ---> SALE (one product can have many sales, but one sale can only have one product) - see note below.
SALE ----- SALE_HARDWARE (this is a one to one relationship, and SALE_HARDWARE will only have data for some SALEs which are hardware based).
--
Note: This is a very simplistic example. Above I mentioned that PRODUCT ---> SALE (one to many) but in reality this wouldn't be true. A sale can contain many products. That is why a SALE or ORDER is usually divided into ORDER_ITEMS and each ORDER_ITEM contains a single PRODUCT.
Hope this makes sense, and I hope this touches on how to design your database using normalization. Let me know if you have questions, or if you want to change your question to focus on a specific few entities that you want to further normalize.
It's missing a lot of details, but I would go for something like that. Obviously you need to fill in the gaps!
So you get a product table, a customer table. The Hardware - Software does not realy mater, but if you must, add a Type column to your products.
A line is one product with quantity. An Order is a bunch of lines grouped together. Then again, a Lease is also a bunch of lines grouped together, but with additional conditions then a sale.
Product
Productid
ProductName
Price
ToShip: boolean, can this product be shipped or not?
....
Customer
Customerid
Firstname
Lastname
ShippingAddress
BillingAddress
Phone
...
Order
Orderid
Buyer: FK to Customer.Customerid
ShippingAddress: boolean, true == use address from Customer
false == use address here
ShiptoAddress
Shipped
TrackingNumber
Line
Lineid
Productid: FK to Product.Productid
Quantity
DiscountPercentage
Order <-> Line
Orderid: FK to Order.Orderid
Lineid: FK to Line.Lineid
Lease
Leaseid
Leaser: FK to Customer.Customerid
Terms
...
Lease <-> Line
Leaseid: FK to Lease.Leaseid
Lineid: FK to Line.Lineid
Support: support contract
Supportid
Term
SuportLevel
...
Support <-> Line
Supportid: FK to Support.Supportid
Lineid: FK to Line.Lineid
Lease could be linked to another table that specifies the LeaseType (standard conditions, lease agreement, ...). Something similar for Support.
This allows the same product to be purchased, leased or supported.
Just ideas, adapt as required.
I am creating a sports collection database of different sports and i am confused of some sort on what tables and primary keys/foreign key combo to use the requirement is as follows:
Should be in a 3rd Normal Form or at least in 3NF.
Here is the Full Description on what I want to do:
Design a database for a sports collection of cards.
You only purchase cards with current market value( at the time of purchase) that are at least $100.00. Your collection about 1000 cards
You collect all kinds of sports cards, from football, basketball, hockey and etc
These cards you collect are produced by different vendors such as ?Topps, Upper Deck, Leaf and Panini.
The collection spans many years of collection, some cards even date back to early 1900s, but there are cards made even before this
The condition of your cards vary too and are grade according to the 10-point PSA grading standards. (Grading table)
Everytime you purchase a card, you must know the date of purchase, cost of purchase, the market value of that purchase, whom you purchased it from, sport, the individual on the cards, card number and etc.
After completion of purchase, you send the card out for grading about a week later, you want to be able to keep track on when the card was sent out for grading, status of the grading, graded assigned to the card , when it was return by the grading company and receipt of the returned card. for tax purposes, you also want to know the fee paid for the grading service (grade table)
you do buy and sell cards, so you also want to know how much you sold the card for for, when it was sold, to whom it was sold, shipping fee if applicable and any relevant data pertinent to sale transaction. You are free to include any additional data that you believe is important to the table.
Here is my current database so far... I feel like i am missing something and I did not follow the requirements properly
It looks like a pretty good start. I have the following observations about your tables/structure:
CardSellers: should only store info about the CardSeller; the only values it should have are SellerID and SellerName
Vendor: should not have CardId
Grade: SellerID doesn't belong here
Card: looks good
CardBuyers should not have DateOfPurchase or CostOfCard or Shipping Fee; those three members belong in CardTransaction. In fact, "DateOfPurchase" should be "DateOfTransaction"
Also, since the Vendor table should only store Vendor data, and the Card table should only store card data, you also need a M2M (many-to-many) table to connect the two; this should have three members: ID (PK), CardId (FK), and VendorId (FK)
UPDATE
Remember two things about table design:
(0) A table should only contain data about the object its named for and only references to other tables (via a FK - see below)
(1) DRY (Don't Repeat Yourself - IOW, don't store the same data in multiple places; instead, store a link to it, where needed, via FK (Foreign Key) fields referencing PK (Primary Key) fields).
As far as the actual design of the tables, this makes sense to me:
CARDS
-----
CardId (PK)
VendorId (FK)
CardFirstName
CardLastName
CardType
CardYear
MarketValue
Rarity
CollectionNumber
COLLECTORS (Buyers and/or Sellers; no need to have separate tables for them)
---------
CollectorId (PK)
CollectorName
CollectorAddress
TRANSACTIONS
------------
TransId (PK)
CardId (FK)
BuyerId (FK) <= CollectorId in the Collectors table
SellerId (FK) <= CollectorId in the Collectors table
TransactionDate
Price (if it may differ from CARDS.MarketValue)
GRADE
-----
GradeId (PK)
CardId (FK)
Points
AssignedGrade
Qualifiers
Status
CardFee
GradedDate
ReturnedDate
VENDORSLU ("LU" stands for "Lookup")
---------
VendorId (PK)
VendorName
CARDTYPESLU
-----------
CardTypeID (PK)
CardTypeDescription
RARITYLU
-----------
RarityID (PK)
RarityDescription
You may find there are other fields you need to add, too, but that should be close. You might even want additional lookup tables, such as for "Qualifiers" and "Status" in the GradeTable.
You might also want a SPORTSLU table, and then add a SportId FK to the CARDS table (where if SportId == 1, it's a football card, if it's 2, it's a basketball card, &c).
Note, though, that as prevalent and historically significant as Relational Databases are, there is another animal called "Non-SQL" databases (such as MongoDB) which are more free-form/loosey-goosey/I'm okay-you're okay/anarchistic, which allow you to have records, or "documents" that can omit or add whatever members it wants on the fly. Relational Databases can be compared to Classical music (Bach, Mozart, &c) whereas Non-SQL are more like Jazz (free-flowing, improvisational).
And BTW, why no mention of Tiddlywinks? Football, Baseball, etc., are fine, but no Tiddlywinks (or Bocci Ball, for that matter)?!?
Can somebody make sure my database is in the 3rd normal form, and if not, explain why not?
I need the DB to only have 3 tables. So here it is:
Customer No. (PK) Store No. (PK) Sale No. (PK)
Name Location Customer No. (FK)
Telephone Revenue Store No. (FK)
Address Total
Purchases($) Paid
Store No.
Here are what your three tables should be: Table 1: Customer
Customer No. (PK)
Name
Telephone
Address
then Table 2: Store
Store no. (PK)
Location
then Table 3: Sale
Sale No. (PK)
Customer No (FK)
Store No (FK)
Total
Paid_yes_no
If you are trying to track partial payments, etc. through the Paid column, then it would be a separate table (and a much more complicated database). However, if your Paid column just indicates whether the bill has been paid or not, the above should work.
Perhaps you need a Date field there as well?
There are a few problems, some of this may be as the specification is for homework rather than the real world.
Store No. in Customers is a duplicated column It's reasonable to expect that a business with multiple stores have customers who use multiple stores - unless your specification says otherwise and in which case the taxonomy (naming) should be expanded, you could consider First Store No. or Home Store No. instead. Also it should be marked up as a foreign key if it is to remain.
Purchases($) in the customers table is reliant on other data which will change. Since it is derived from other information you should not store it.
Address is not a single column - it has multiple parts like Street, City, State, Country & ZIP Code may in turn require extra tables details to fully satisfy 2nd Normal Form. Similarly Telephone is unlikely to be just one number.
Each thing you need to know should appear once and once only. If you can calculate it from something else you should do that rather than store the answer. In the real world you might sometimes cache some information in a table or batch process it for performance, but those would be applied later and only if necessary.
A brief overview of database normalisation is at http://databases.about.com/od/specificproducts/a/normalization.htm which you should probably look through before reworking your project.