Normalize a table with tightly coupled data - sql

I currently have a table that stores the materials used to create an item
Item (material1, material2, material3)
Another material has recently been added. However, I want to normalize this table so that in the future, adding a new material won't need a new column to be added to the database. I extracted the materials into the following junction table
ItemJuncMaterial (id, itemId, materialid)
However, the catch is that the order of the materials matter. So this junction table won't allow me to run this query based on materials to get the item
select itemid from ItemJunMaterial where materialid in (1,2,3)
This can return items that use 2,3,1 or could even use two materials 1,2. Is there a better way to split up this table to normalize it and make it more dynamic?

You should consider a "bill of materials" (BOM) pattern (see here or here). The intersection of a BOM can include extra information about the composition, such as quantity of each component. You could easily include the sequence or priority of the component in that intersection just as easily.

Related

I am making a SQL database of categories and subcategories. What is the best way to link these tables?

The database has a table called "categories" with columns CATEGORY_ID(primary key) and CATEGORY_NAME.
I have subcategories for each category.
For better accessing which is the best method from the below methods.
Method 1: The "CATEGORY_ID" column in the "categories" table is a FOREIGN KEY in the "subcategories " table.
Method 2: Maintaining a separate table for each category representing the subcategories.
I prefer to use same table for category and sub category
like
Table Categories
[CATEGORY_ID, CATEGORY_NAME, PARENT_CATEGORY_ID]
In case you don't know how many sub categories are there.
This scenario is just an example, the scenario is as follows: We have a product table where all the records of products are stored. Same way we will have customer table where records of customers are stored. The daily sales keep the record of all the sales. This sales table will keep record of which product who has purchased. So linking is to be done from Sales table to product table and customer table.
The query to link the two tables is as follows:SELECT product_name, customer.name, date_of_sale FROM sales, product, customer WHERE product.product_id = sales.product_id and customer.customer_id >= sales.customer_id LIMIT 0, 30
It is better to go with Method 1 since it is more scalable.
Let me elaborate on this. If we go with method 1, we need to maintain 2 tables only that is Categories and Subcategories. In future if we have new categories or subcategories we can directly deal with this 2 tables.
If we consider same situation with Method2 then we need to create new tables every time, this may become maintenance overhead.
Let me be a bit more direct. You explain in a comment that Method 2 is a separate table for each category. If so, then Method 2 -- in general -- is just wrong.
There are two methods for storing this type of information. One is a Categories table with a (single) Subcategories table. The Subcategories table would have CategoryId, a foreign key reference back to Categories. This is the normalized data model.
The second method is to store everything in one table. Each row would be a category/subcategory combination. Information about a given category would be duplicated across multiple rows, so this is not a normalized approach. However, this is a typical approach when doing dimensional modeling for decision support systems.
If the subcategories are just names of things, there is a third approach, which would be to store a list of the subcategories within each Category row. The list would not be a delimited string. It would be JSON, a nested table, XML, array, or similar collection data type supported by the database you are using. I am mentioning this as a possibility, but not recommending it.

Nesting Tables in SQL Server Express

I am creating a purchase order system where someone can store details of their purchase. So I created a database, with tables for supplier information from which we will buy stuff and another table where we store what we are buying.
In the PurchaseOrder table, there are columns for :
PurchaseOrderNo (Primary)
BuyerInitials
DateOfPurchase
ProjectCode
Items (linking to the PurchaseItems table)
I want to add another column with Items' details, so I created another table PurchaseItems which has the following columns:
PurchaseOrderNo. (this would be repeat for each part)
PartNo
Description
Quantity
UnitAmount
VATAmount
TotalAmount
Logically it seems simple, but I can't seem to get my head around on how I would link the tables. Thank you very much for the help :)
Create a seperate table say OrderedItems which maps the PartNo and PurchaseOrderNo. This avoids the repetition of PurchaseOrderNo in each row and also maintains the relation between PurchaseOrder and PurchaseItems table.

How do I create hierarchies across dimensions?

I am using a snowflake design because I do not have huge volumes of data to worry about.
I have a Categories table and a Subcategories table and a Product table and from these tables I create a dimension with a
Category > Subcategory > Product
hierarchy.
I also have a Territory table, Country table, and a Customer table from which I create a dimension with a
Territory > Country > Customer
hierarchy.
This all works well, but what if I want to create other hierarchies, such as:
Territory > Country > Category > Subcategory > Product
or
Category > Customer > Product
or any other possible combination that the client wants to see.
I am unclear on how to do this with my existing table set.
Please ask for more information if I have not been clear.
This is not possible without making major changes in the cube design.
If you build an additional dimension which combines both dimensions into one.
You can achieve this. In this case you end up with 3 dimensions instead of 2.
To combine 2 dimensions, for each lowest level key combinations of both dimensions you need to create a new artificial key as the lowest key of the new dimension.
Then you can create the new attributes/hierarchies as usual.
Afterwards you can create a new unnatural hierarchy combining levels from unrelated hierarchies/attributes. This is what you want to achieve.
Since this new hierarchy will be unnatural, it will not perform very well but it will work.
Actually having 3 dimensions will not be necessary, after you combine 2 of them into a new one. You can get rid of the original 2 dimensions, since you can achieve the same functionality with the new one.

Improvement on database schema

I'm creating a small pet shop database for a project
The database needs to have a list of products by supplier that can be grouped by pet type or product category.
Each in store sale and customer order can have multiple products per order and an employee attached to them the customer order must be have a customer and employee must have a position,
http://imgur.com/2Mi7EIU
Here are some random thoughts
I often separate addresses from the thing that has an address. You could make 1-many relationships between Employee, Customer and Supplier to an address table. That would allow you to have different types of addresses per entity, and to change addresses without touching the original table.
If it is possible for prices to change for an item, you would need to account for that somehow. Ideas there are create a pricing table, or to capture the price on the sales item table.
I don't like the way you handle the sales item table. the different foreign keys based on the type of the transaction is not quite correct. An alternative would be to replace SalesItem SaleID and OrderId with the SalesRecordId... another better option would be to just merge the fields from InStoreSale, SalesRecord, and CustomerOrders into a single table and slap an indicator on the table to indicate which type of transaction it was.
You would probably try to be consistent with plurality on your tables. For example, CustomerOrders vs. CustomerOrder.
Putting PositionPay on the EmployeePosition table seems off to... Employees in the same position typically can have different pay.
Is the PetType structured with enough complexity? Can't you have items that apply to more than one pet type? For example, a fishtank can be used for fish or lizards? If so, you will need a many-to-many join table there.
Hope this helps!

Table Design For Multiple Different Products On One Order

If I were to have an online shopping website that sold apples and monitors and these were stored in different tables because the distinguishing property of apples is colour and that of monitors is resolution how would I add these both to an invoice table whilst still retaining referential integrity and not unioning these tables?
Invoices(InvoiceId)
|
InvoiceItems(ItemId, ProductId)
|
Products(ProductId)
| |
Apples(AppleId, ProductId, Colour) Monitors(MonitorId, ProductId, Resolution)
In the first place, I would store them in a single Products table, not in two different tables.
In the second place, (unless each invoice was for only one product) I would not add them to a single invoice table - instead, I would set up an Invoice_Products table, to link between the tables.
I suggest you look into Database Normalisation.
A question for your data model is You need a reference scheme will you use to identify products? Maybe SKU ?
Then identify each apple as a product by assigning an SKU. Likewise for monitors. Then use the SKU in the invoice item. Something like this:
product {sku}
key {sku};
invoice_item {invoice_id, sku}
key {invoice_id, sku} ;
apple {color, sku}
key {color}
key {sku};
monitor {size, sku}
key {size}
key {sku};
with appropriate constrains... in particular, the union of apple {sku} and monitor {sku} == product {sku}.
So Invoice table has a ProductID FK, and a ProductID can be either an AppleID (PK color) or MonitorID (PK resolution)?
If so, you can introduce a ProductTypeID with values like 0=apple, 1=monitor, or a isProductTypeApple boolean if there's only ever going to be 2 product types, and include that in the ProductID table PK.
You also need to include the ProductTypeID field in the Apple table and Monitor table PK.
I like name-value tables for these...It might be easier to redesign so it goes 'Product' and then 'product details'...product details holds the product id, the detail type and then the value. This would allow you to hold apples and monitors in the same table regardless of identifying attribute (and leave it open for other product to be added later on).
Similiar approach can be taken in the invoice table...have a 'product_type' column that tells you which table to look into (apple or monitor) and then a 'product_id' that references whatever ID column is in the apple/monitor table. Querying on a setup like this is a bit difficult and may force you to use dynamic sql...I'd only take this route if you have no control over doing the redesign above (and other answers posted here refer to)
First solution is preferential I would think...change the design on this db to the name value pair with the products and you'll save headaches writing your queries later.