What is the best DB schema to handle exceptions and prevent redundancy? - mysql

There are some products that can be sold in multiple units and the base unit is kilogram. The unit of each product has different weight, for example a Bundle of product A is 20kg but a Bundle of product B is 30kg
The following is my initial design.
product:
id name
product_variation:
id product_id name price
product_variation_unit:
id product_variation_id unit_id
product_variation_unit_weight:
product_variation_unit_id weight
The problem is than most of the variation of a product have the same unit and weight. So here is my solution but I'm not sure it's a good idea:
selectable_unit:
id selectable_id selectable_type unit_id
1 10 product 100
2 20 product_variation 101
selectable_unit_weight:
selectable_unit_id weight
And when I want to get the unit and weight of a variation, first I will check the variation and if there isn't, I will check it's product.
I't a little complicated, can you help me to find a better solution or improve it?

Have a look at the following diagram (Oracle Data Modeler notation). Usually, a price is depending on the SKU (stock keeping unit) and the period; a weight is depending on the SKU (packed product).
An SKU weight is limited by units allowed for its product (foreign key contains 2 columns).
SKU.value is the value in the unit to sell, i.e. kg, pcs, liters etc.

Related

discount entity for ERD- onine shopping

I'm currently making an ER diagram for my product model. But I'm confused that the DISCOUNT needs an entity to connect with the product module or it can just be an attributes of the product?
my current product module:
the
PRODUCT
PRODUCT_ID(PK)
PRODUCT_NAME
PRODUCT_PRICE
PRODUCT_TYPE
PRODUCT_COLOUR
PRODUCT_SIZE
STOCK_UNIT (FK)
this is the entity i try to make for DISCOUNT
PRODUCT_ID (PK,FK)
ADMIN_ID(FK)
DISCOUNT_DATE
DISCOUNTED_PRICE
In my scenario, some of the specific product prices can be discounted with value/ per centage. But I am confused that do i need to put the discount value/percentage as an attribute or an entity in the product module because there are only some products that have the discounted price.
I hope that my explanation is clear enough ><
Based on question and comments, I suggest:
Discount Table
--------------
DISCOUNT_ID (PrimaryKey)
PRODUCT_ID (ForeignKey)
IsPERCENT (Bool)
DISCOUNT (Float|Double)
FROM_DATE (DateTime)
TILL_DATE (DateTime)
IsPercent should be True if discount is to calculated using Percentage.
Discount should be value (treated as percent or Currency depending on IsPercent)
Also in your program, validate that Discount value doesn't go above 100 if IsPercent is TRUE

Better to have one master table or split into multiple tables?

I am creating a database and I am unsure of the best way to design my tables. I have a table of real estate properties and I want to store information about those properties - e.g. bedrooms, bathrooms, size... I may have additional information I want to store in the future if it seems useful - e.g. last purchase price or date built, so I need to be flexible to make additions.
Is it better to create a separate table for each "characteristic" or to have one table of all the characteristics? It seems cleaner to separate the characteristics, but easier programming-wise to have one table.
CHARACTERISTIC TABLE
id property_id characteristic value
1 1 bedrooms 3
2 1 bathrooms 2
3 1 square feet 1000
4 2 bedrooms 2
...
OR
BEDROOM TABLE
id property_id bedrooms
1 1 3
2 2 2
...
BATHROOM TABLE
id property_id bathrooms
1 1 2
...
Forgive me if this is a stupid question, my knowledge of database design is pretty basic.
I would suggest a middle ground between your two suggestions. Off the cuff I would do
property table (UID address zip other unique identifying properties)
Rooms table ( UID, propertyID, room type , room size,floor, shape, color, finish, other roo specific details ect..)
Property details (uid, propertyID, lot size, school district, how cost, tax rate, other entire property details)
Finally a table or two for histories eg.
Property sales history(UID, PropertyID , salesdate, saleprice, sale reason, ect..)
Often grouping your data by just "does it match" logic can yield you good results.... care needs only be taken to account for 1to1 and 1tomany relationship needs of tables.
I am focused to this:
"I have a table of real estate properties"
Now as far as i knew you has to be a different type of:
Houses
Bedrooms
Comfort room and so on.
For further explanation:
You has to be a table of:
1. House type
2. House names,description,housetypeid,priceid,bedroomid,roofid,comfortroomid and any other that related to your house.
3. Bedroom type
4. Comfort room type
5. Dining type
6. roof type if it has.
7. House prices
8. Bathroom type
something like that.
One table with a few columns:
Columns for price, #br, #bath, FR, DR, sqft and a small number of other commonly checked attributes. Then one JSON column with all the other info (2 dishwashers, spa, ocean view, etc).
Use WHERE clause for the separate columns, then finish the filtering in you client code, which can more easily look into the JSON.

Storing combinations of item properties in database

I have a problem of such:
Let's say I have an item, a CUP for example. I want to sell it, but want to allow the user to pick CUP properties, such as Size, Color, Material. When the user will select Size (maybe Large), color (maybe Black) and Material (maybe Glass) then I need to show him, that we have 20 such Cups in warehouse and the cost is $25 each. And now: I don't know how to store those combinations in database.
Here is my ultra stupid solution:
For each combination I will have a column, yet, adding any new combination might be painfull as well, as removing some, I will have to map them somehow, well...
Id | Product Name | LargeBlackGlassPrice | LargeBlackGlassCount | SmallBlackGlassPrice | SmallBlackGlassCount | Medium...
stupid idea, but as for now didn't hit anything better :/
Hope it's clear what I want to achieve.
Thank you
Consider the following ERD:
The system administrator maintains a list of product categories, these may include, for example, cups. The administrator also maintains a list of features. These could include size, colour, material, and anything else that they decide is potentially important for any type of product. The administrator can then create an intersection of categories and features to indicate which features matter for a particular product category.
This establishes the "rules" for a catalogue of products. Which types of products do you have and what is important to know about each of these types products.
Now, to store the products themselves, you have the SKU table. Each individual product, for example: Large Black Glass Cups is stored in this table. You can store the current price of this product here. You can also store the stock on hand here, although I've recommended elsewhere to never store stock quantity directly. Inventory management is not the basis of your question, however.
For any particular product (SKU) you then have a list of product features where the specific values of each specific product are stored. The features that matter are the ones defined by the product's category as listed in the CATEGORY_FEATURE table.
On your website, when a customer is searching for items in a PRODUCT_CATEGORY, (e.g. Cups) you show them the list of CATEGORY_FEATUREs that apply. For each feature, you can create a drop down list of possible values to choose from by using:
select distinct PF.value
from CATEGORY_FEATURE CF
inner join PRODUCT_FEATURE PF
on CF.product_category_id = PF.product_category_id
and CF.feature_id = PF.feature_id
where CF.product_category_id = CategoryOfInterest
and CF.feature_id = FeatureOfInterest
order by
PF.value
This design gives your administrator the ability to define new product categories and product features without having to make database schema or code changes.
Many people are likely to point out that this design uses the Entity-Attribute-Value (EAV) pattern, and they are equally likely to point out that EAV is EVIL. I agree in principle that EAV is to be avoided in almost all cases, but I have also asserted that in some cases, and in particular in the case of product catalogues, EAV is actually the preferred design.
Table1 => Cup Master
Fields => Cup Id | Product Name
Example =>
1001 | CUP A
1002 | CUP B
Table2 => Property Master
Fields => Property_Id | Properties
Example =>
1 | LargeBlackGlass
2 | SmallBlackGlass
3 | MediumBlackGlass
Table3 => Inventory Master
Fields => Cup Id | Property_Id | count | price_per_piece
Example =>
CUP A | 1 | 3 | 45/=
CUP A | 2 | 2 | 40/=
CUP A | 3 | 2 | 35/=
CUP A | 1 | 3 | 45/=
CUP A | 2 | 2 | 40/=
NOTE: A cup with a particular property might be available and with other property might not.
Let try to reason how to solve your task. I will describe general conception and split it in some steps:
Define types of products that you are going to sell: cup, plate, pan and so on. Create table products with fields: id, name, price.
Define colours of products: black, red, brown. Create table products_colours with fields: id, name, price.
Define sizes of products: small, medium, large. Create table products_sizes with fields: id, name, price.
In simple case all types of products will have the same price and will store in table products.
In simple case additional price for colours and sizes will be the same for all types of products and will be stored in tables products_colours and products_sizes.
Create table customers_products with fields: id, products_id, products_colours_id, products_sizes_id, quantity.
Write a query for join all table together to fetch all products with colours, sizes and all prices from db.
In the script iterates through all rows and calculate price for every product as a sum of product price, size price and colour price.
To sum up: this is very basic implementation that doesn't include things like brands, discounts and so on. However, it gives you understanding how to scale your system in case of adding additional attributes that affect the final price of products.

count 0.5 for some IDs

So this is for my dissertation and it is coming allong pretty well. almost finished it now xD
Anyway, I'm making a pub Epos system in access and its all OK, except now I have reached the stock control.
To get the query (Stock = Stock - Sales) I need to do a count query, which is easy enough, though the problem with pubs is they often serve half pints...
Is there any way to get the count SQL function to count certain ProductID's as 0.5?
This is a part of the table, and Product ID 2,4,6,8 and 10 are all relating to half pints and so count needs to recognise them as 0.5 instead of 1.
[URL=http://imageshack.us/photo/my-images/688/2121212e.png/][IMG]http://img688.imageshack.us/img688/64/2121212e.png[/IMG][/URL]
Thanks
Sam
It seems that you need to separate products purchased from products sold, lets say you called products sold "servings".
product (productId, supplierId, orderQuantity, reorderTrigger)
serving (servingId, productId, servingDesc, volumeOfServe)
this way you can have two servings of the one product (eq guiness)
servingDesc - "Guiness 1/2 pint" volumeOfServe - 0.5
servingDesc - "Guiness pint" volumeOfServe - 1

Database Design: how to model generic price factors of a product/service?

I'm trying to create a generic data model that will allow for a particular product (indicated by the FK product_id in the sample table below) to specify 0 or more price "factors" (I define "factor" as a unit of price added or subtracted in order to get the total).
So say there is this table:
===============================
price
===============================
price_id (PK)
product_id (FK)
label
operation (ENUM: add, subtract)
type (ENUM: amount, percentage)
value
A book's price might be represented this way:
====================================================================
price_id | product_id | label | operation | type | value
====================================================================
1 | 10 | Price | add | amount | 20
2 | 10 | Discount | subtract | percentage | .25
3 | 10 | Sales Tax | add | percentage | .1
This basically means:
Price: $20.00
Discount: - $5.00 (25%)
--------------------
Sub Total: $15.00
Sales Tax: $1.50 (10%)
------------------------
Total: $16.50
A few questions:
Is there anything obviously wrong with the initial design?
What if I wanted to create "templates" (e.g. "general merchandise" template that has "price", "discount" and "sales tax" fields; a "luxury merchandise" that has "price", "discount", "luxury tax" fields) - how would I model that?
The above model works if each record applies to the total of the preceeding record. So, in the example, "sales tax" applies to the difference of "price" and "discount". What if total was not computed that simply? For example: A + B + (A + 10%) - (B - 5%). How would I model that?
Also, what if the "percentage" type doesn't apply to the immediately preceeding row (as implied by question #3) and applied to more than 1 row? Do I need another table to itemize which price->price_id the percentage applies to?
First of all you need a model of price labels, which is simple:
price_labels
id | label
1 | Price
2 | Discount
3 | Tax
Then a slightly modified version of the sample table that you've given:
products_prices
price_id|product_id|label_id|divider|value
1 10 1 1 20
2 10 2 100 -25
3 10 3 100 10
Here I just substituted the label with the corresponding id from the price_labels table as a foreign key. Additionally, I omitted the type field which is trivial since value can be positive or negative float number. I added the divider column to enable the percentage parameter. I think it is more easily read this way as well, since you say (and think) "minus twenty-five percent" not 0.25 .
Now the expression "abstraction" part is a bit more complicated and there could be a lot of solutions.
price_expressions
product_id | date_from | date_until | expression
10 |2011-11-02 04:00:00 |2011-11-12 04:00:00 | (SELECT divider*value from
products_prices
WHERE product_id=%PRODUCT_ID%
AND label_id=1)*
(SELECT 1+value/divider from products_prices
where product_id=%PRODUCT_ID% AND
label_id=2)*
(SELECT 1+value/divider from products_prices
where product_id=%PRODUCT_ID% AND
label_id=3)
In the expression field you can store a complex SQL statement in which you can just replace the %PRODUCT_ID% placeholder with the product_id value from the same row:
SELECT REPLACE(expression,'%PRODUCT_ID%',CAST(product_id AS char))
AS price_expression FROM price_expressions
WHERE product_id = 10 AND date_from>=DATE_OF_PURCHASE
AND date_until<=DATE_OF_PURCHASE
There are two possible variations of this the way I see it:
You can change the product_id=%PRODUCT_ID% and label_id=N condition with just a price_id=N since you already have it stored in the products_prices table
You can use another expression format e.g. %PRICE_ID_1%*%PRICE_ID_2 and perform substitutions and calculations on the application level not directly in SQL
Hope this helps.
This seems a little over-engineered.
1) Wouldn't the sales tax percentage be a factor of where the item was purchased and not which item was purchased? I could see a field for "IsTaxable", but specifying the rate for each items seems incorrect.
2) Are you sure you need to incur the cost of making this generic? Are you already fairly certain there will be more factors in the future? If not, don't overcomplicate it.
Suggested Design:
- Add columns to the products table for IsTaxable, DiscountPct, and Unit Price.
- Store the Sales tax percentage in another table. Probably the invoice table.
Regarding your question 1:
There is a potential functional dependency between label, operation and type. For example, a discount might always imply subtraction and percentage. If so, the data model can be normalized by moving these fields to a separate table with label as a PK.
BTW, a de-normalized data model may be a legitimate tool for improving performance and/or simplicity.
Regarding your question 2:
Here is a model that allows easy "templating":
The final price of a product is calculated by applying the series of steps on PRICE, in order defined by STEP_NO. Multiple products can easily share the same "template" (i.e. the same PRICE_ADJUSTMENT_ID).
Regarding your questions 3 and 4:
You'd need to model a full expression tree, not just a "linear" series of steps. There are several ways to do that, most of them fairly complicated in relational paradigm. Perhaps the simplest one is to keep the data model similar to above, but treat it as Reverse Polish Notation.
For example...
A + B + (A + 10%) - (B - 5%)
...could be represented as:
OPERATION TYPE VALUE
---- ---- -----
value A
value B
add
value A
percentage 10
add
add
value B
percentage 5
subtract
subtract
Are you sure you actually need this kind of functionality?
If some price factors are dependent on the type of the item, then you'd have a set of price factors linked to entities in an ItemType table, and ItemType would be a property of the item entity (foreign key referencing ItemType). If other price factors are linked to the locale in which the item is being sold or shipped (e.g. sales tax), then those factors would be linked to Locale and would be invoked based on the customer's address. You would typically apply item-type factors at the line-item level, and locale-driven factors to the invoice total. Sin-tax would be linked to an ItemTypeLocale dyad, and applied at the line-item level.
1/ I think you also need to consider sequence
e.g. Price - discount + sales tax is obviously acceptable but Price +sales tax - discount is not nor is Price - (discount + sales tax)
2/ I would consider having price in another table. Is this not a detail of the item being sold? E.g. Widget, blue, $20.00. Whereas your factors are a detail of sales type. Presumably you could have one set of factors for a walk-in retail sale, another for a on-line sale and a third for a wholesale sale. You could calculate the actual price for these three sale types from the base price * factors.
3/ I think you need more tables; e.g. maybe Item, Sale type, and factor_details and factor_rules. It may be that your sale type is covered by your example of Luxury item in which case (if an item is only ever one sale type) this could be in the item table. Factor_rules would detail the calculation formula and factor_details the values.
I find this quite interesting. I would appreciate you updating this question with your experiences once you have worked this through.