Using inheritance to solve a design problem - database

I need a table that stores items and tracks when an item is...
queued
marked for shipping
shipped
marked for return
returned
The table also needs to tell me how many items a customer...
has received in a month
has at home at this time
I tried using inheritance. I assigned each step a typeId (from 1 to 5, each id representing the current step in the workflow). This approach is not ideal because updating a workflow step erases history.
For example, if an item moves from shipped (typeId 3) to returned (typeId 5) we lose an accurate count for shipped items.
How should I approach this? Also, I prefer to keep the data in one table unless I get a compelling reason not to.
Update
Items are mailed to customers incrementally. There are limits to how many items a customer can receive within a month period, and limits on how many items a customer can have at home at any given time. For this example, let's assume 4 for earlier and 2 for the latter. A customers queue can have any number of items. For this reason, items in the queue need to be ranked so the order of items sent can be according to the customers preference.
Items that have shipped already will need to fall out of ranking (the customer can no longer modify rank after an item is sent).

No inheritance here. Time fields are actually date-time. A row is entered into the Tracking table when a customer adds an item to the queue. Other time columns from TimeMarkedShip to TimeReturned are NULL until the action happens. The TimeQueued is part of the primary key in order to allow a customer to rent an item more than once (sounds like video rentals to me).
To count items that a customer has at home you could use something like
select count(1)
from Tracking
where CustomerID = 1755
and TimeShipped is not NULL
and TimeReturned is NULL ;

Rather than a typeID for the current step, it looks like you need a boolean column for each step. Then when you want to count the "net shipped" items, you can subtract the "returned" items from the "shipped" items.
In addition, if you want to track the history, you could make each of these steps a nullable date field, so that you can see that an item was shipped on 3/5/11 and returned on 4/1/11. This may help if you're using this table in other ways, such as managing your shipping/receiving or billing. A NULL, of course, would indicate that the step has not been performed (yet).

Related

Data modeling : gas station managing

I need to create a database to manage a gas station.
I'm thinking of a basic product inventory and sales data model, but it need some changes.
See http://www.databaseanswers.org/data_models/inventory_and_sales/index.htm. This is how they proceed: the manager keep tracks of the inventory and sales twice a day, each time a gas pump attendant is in charge, and takes the responsibility of the sales.
How can I keep track of this ?
Using the Model that you provided you could use the first Model as reference:
And I would use all the six (6) tables namely:
1) Products
2) Product_Types
3) Product_In_Sales
4) Sales
5) Daily_Inventory_Level
6) Ref_Calendar
But I had to make some changes by alteration and adding:
First I need to include SalesPerson table that would have at least the following fields
1) SalesPersonID
2) Lastname
3) Firstname
4) Alias
In line with that I therefore need to add SalesPersonID as Foreign key in
my Sales table.
Now since you want to have twice a day Inventory then you could approach in many ways
you could add single primary key for Daily_Inventory_Level table or you could add a new field named Inventory_Daily_Flag which has either only the value of 1 or 2. If 1 that means that's the first inventory and if 2 that means that's the second inventory for the day. And that means by the way that you're Primary and Foreign Key at the same time would no longer be just Day_Date and ProductID but also Inventory_Daily_Flag for Daily_Inventory_Level table.
And also in line with that, that means you need to also to add a field in your Product_In_Sales like FlagForInventory with Boolean as Data Type.
So, let's say a Supervisor came in to do the first inventory, then the products sold
in Product_In_Sales for the day would be flag as True for the FlagForInventory and
then would be transferred to Daily_Inventory_Levels with Inventory_Daily_Flag field
as 1 to indicate as the first inventory and of course the Level also would be updated.
And so when the days end and the 2nd inventory is to be executed then those
sales for the day from Product_In_Sales table whose FlagForInventory is false then
it would be flag as True for FlagForInventory and then transferred again to Daily_Inventory_Levels with Inventory_Daily_Flag as 2 indicating the second inventory.
And of course you need to update the Level as well.
Does it make sense? If not I could always change the approach? ;-)

How to manage changed items and their previous names in database

How does one handle situation when you have sales orders and items tables, and then at one point in time you have to change an item. The change will also show up on sales order that have that item. However, lets say that at the time the sales order was place the information was correct but changed later. I don't want older SOs to change what they show for line items and I don't want to have to make new items because it will confuse me later which item is correct.
I noticed that in OpenERP it does just that, keeps the name of part number and description on sales order even if you changed it after sales order was made.
If you are creating new database restructure your Item table. Create a table (for e.g. ItemHistory). have a ItemID and ItemTypeID and DateCreated Fields on it.
ItemID should be used for orders and ItemTypeID + DateCreated will help you to get the current Item.

Comments/Suggestions on database design - Warehouse Stock Management

I'm currently creating a stock management system that uses multiple warehouses (with sub locations) and since this is my first big project I would love some feedback.
Let me show you what I have done so far...
Link as Im still new here
You first need to create a Warehouse, then you can create a Location within that Warehouse.
You can also create an ItemType (ItemGroup), then you can create an Item for that group.
Once you have an Item and Location you can add Stock, the Stock table has a composite key so that duplicates cant be added. I also added a constraint so that you could not enter an Item of the wrong ItemType, same constraint on the Warehouses/Location.
I then need to keep records of each piece of stock, SerialisedItems and NonSerialisedItems. Example: If non serialised stock is added with a quantity of 10 then I currently create 10 rows inside the NonSerialisedItems table (1) that are set to ‘in stock’ with the relevant stock information. If they change the amount of stock then rows would be deleted or added (2).
I could also do with a Van table somewhere that is similar to Warehouse, but think I would have to change the Warehouse table to something like Storage that references two tables, Warehouse and Van?
(1) I currently have a TransactionScope on my page adding x number of rows, Is this the best way to handle that?
(2) The Quantity amount in the Stock table would have to count the number of rows for that item and then update the Quantity each time stock is added or removed, any problems here? - Both Questions Fixed - Only create rows for serialised items.
Any other problems?
Well that’s what I have done, if its good or terrible let me know.
Also if there are any pitfalls I should be looking out for that would also be great to know.
Thanks
[EDIT]
Thanks to Neville K I have made a few changes...
Link to new and improved database
This seems to make a lot more sense! Think I had been staring at it to long yesterday!
Firstly, this is pretty much a solved problem - the best resource I know of is the "data model resource book" series; there's a very flexible model for stock maintenance apps in there.
Secondly, your design is not very normalized, and relies on a lot of duplication. Not sure what the reasoning is, but usually, the "stock" table would have a link to "item", but not "itemType" - the fact that an item belongs to an item type is already captured in the relationship between item and item type, and you don't need to duplicate it. The same goes for location and warehouse.
The key change I'd suggest is the concept of a stock transaction, rather than a single "stock" table.
Something along the lines of
TransactionID date itemID locationID quantity
------------------------------------------------------------------
1 1/1/12 1 1 10
2 1/2/12 1 1 -1
3 1/3/12 1 1 20
To find out the current stock for an item, you sum(quantity) group by item; to find the current stock for an item broken down by location, you sum(quantity) group by item, location.
On the first of Jan, there were 10 items in stock; on the second, 1 item was removed, leaving a stock of 9; on the 3rd, 20 new items came into stock, giving a balance of 29.
This design allows you to track change over time, which is a common requirement; it also provides an audit trail by creating transaction meta data (operatorID, invoice number etc.).

Calculated Measure aggregating on certain cells only

I'm trying to figure out how I can create a calculated measure that produces a count of only unique facts in my fact table. My fact table basically stores events from a historical perspective. But I need the measure to filter out redundant events.
Using sales as an example(Since all material around OLAP always uses sales in examples):
The fact table stores sales EVENTS. When a sale is first made it has a unique sales reference which is a column in the fact table. A unique sale however can be amended(Items added or returned) or completely canceled. The fact table stores these changes to a sale as different rows.
If I create a count measure using SSAS I get a count of all sales events which means an unique sale will be counted multiple times for every change made to it (Which in some reports is desirable). However I also want a measure that produces a count of unique sales rather than events but not just based on counting unique sales references. If the user filters by date then they should see unique sales that still exist on that date (If a sale was canceled by that date if should not be represented in the count at all).
How would I do this in MDX/SSAS? It seems like I need have a count query work from a subset from a query that finds the latest change to a sale based on the time dimension.
In SQL it would be something like:
SELECT COUNT(*) FROM SalesFacts FACT1 WHERE Event <> 'Cancelled' AND
Timestamp = (SELECT MAX(Timestamp) FROM SalesFact FACT2 WHERE FACT1.SalesRef=FACT2.SalesRef)
Is it possible or event performant to have subqueries in MDX?
In SSAS, create a measure that is based on the unique transaction ID (The sales number, or order number) then make that measure a 'DistinctCount' aggregate function in the properties window.
Now it should count distinct order numbers, under whichever dimension slice it finds itself under.
The posted query might probably be rewritten like this:
SELECT COUNT(DISTINCT SalesRef)
FROM SalesFacts
WHERE Event <> 'Cancelled'
An simple answer would be just to have a 'sales count' column in your fact view / dsv query that supplies a 1 for an 'initial' event, a zero for all subsiquent revisions to the event and a -1 if the event is cancelled. This 'journalling' approach plays nicely with incremental fact table loads.
Another approach, probably more useful in the long run, would be to have an Events dimension: you could then expose a calculated measure that was the count of the members in that dimension non-empty over a given measure in your fact table. However for sales this is essentially a degenerate dimension (a dimension based on a fact table) and might get very large. This may be inappropriate.
Sometimes the requirements may be more complicated. If you slice by time, do you need to know all the distinct events that existed then, even if they were later cancelled? That starts to get tricky: there's a recent post on Chris Webb's blog where he talks about one (slightly hairy) solution:
http://cwebbbi.wordpress.com/2011/01/22/solving-the-events-in-progress-problem-in-mdx-part-2role-playing-measure-groups/

Invoice database design

The invoice database design, might look something like this...
http://www.databaseanswers.org/data_models/invoices_and_payments/index.htm
Now If the user decides to change/revise the product code/description
It will change the previous order and invoice produce code/description :(
What do you do? Copy the product code description to the invoice table instead?
You basically have two options:
either you make your Products table "time-enabled" (also known as "temporal database"), e.g. you keep the "previous" state of your individual product in your table, and you give every entry a ValidFrom / ValidTo pair of dates. That way, if you change your product, you get a new entry, and the previous one remains untouched, referenced from those invoices that used it; only the ValidTo date for the product gets updated
or:
you could copy the products (at least those bits you need for your invoice) to the invoice - that'll make sure you always know what the product looked like when you created the invoice - but this will cause lots of data duplication (not recommended)
See this other Stackoverflow question on temporal databases as another input, and also check out this article on Simple-Talk: Database Design: A Point in Time Architecture

Resources