MS Visio Category relationships to SQL Server - sql

I'm using MS Visio to model a database and part of the model contains Transaction categories - the parent table has a transactionId, timestamp, amount, and transactionType. There are three child tables - cheque, bank transfer, and credit card, all related to the parent by transactionId.
Is there a specific way this kind of relationship is implemented in SQL Server, or is it just a conceptual model leaving the implementation up to me? If the latter, why have a transactionType column in the parent table if the tables are all related with transactionId - is it just to narrow my queries? That is, if a row in the parent table specifies "cheque" as the transactionType I know that I only have to query/join the cheque child table?
It just occurred to me - is this just an ISA hierarchy, in which case I'd create three distinct tables each containing the columns identified in the ISA parent entity?

This is essentially multiple-table inheritance, although you can model it in the domain as a simple reference relationship if you want.
There are many good reasons to have the selector field/property. The obvious one is so an application or service gets a hint as to how to load the details, so it doesn't have to load every conceivable row from every conceivable table (try this when you have 20 different types of transactions).
Another reason is that much of the time the end user doesn't necessarily need to know the details of a transaction, but does need to know the type. If you're looking at an A/R report from some financial or billing system, most of the time all you need to know for a basic report is the previous balance, amount, subsequent balance, and the transaction type. Without that information, it's very hard to read. The ledger doesn't necessarily show the details for every transaction, and some systems may not even track the details at all.
The most common alternative to this type of model is a single table with a whole bunch of nullable columns for each different transaction type. Although I personally despise this model, it's a requirement for many Object-Relational Mappers that only support single-table inheritance. That's the only other way you'd want (or not want) to model this in a database.

The transactionType in the parent table is useful if you'd like to query over all transactions, for example to sum the amounts per transaction type:
select transactionType, sum(amount)
from transactions
group by transactionType
Without the column, you could still do that by querying on the child tables:
select
case when c.transactionId is not null then 'CHEQUE'
when cc.transactionId is not null then 'CREDIT CARD'
...
end
, sum(amount)
from transactions t
left join cheque c on t.transactionId = c.transactionId
left join creditcard cc on t.transactionId = cc.transactionId
...
group by
case when c.transactionId is not null then 'CHEQUE'
when cc.transactionId is not null then 'CREDIT CARD'
...
end
As you can see, that's much harder, and requires extending the query for each type of transaction you add.

Related

Are multiple nullable foreign keys a bad design?

We have a table to store user financial transactions.
A transaction can be incremental or decremental, we have 3 types of transactions, increase with a payment, increase with receiving of a gift, and decrease with purchase of product, So our transaction table contains 3 foreign keys:
[PaymentId] [GiftId] [RequestId]
Is this a bad design? What better alternative is there?
I think it is complicated to join [Transaction] table with 3 other tables to get details of each transaction to display list of user transactions
It seems like you'd be better off with a column called something along the lines of TransactionType and then just storing the TransactionTypeId in a single column as well. Using these two columns you can represent any number of types of Transactions. You actually find this common in the financial data world with dimension tables that represent things like Cost Type, etc.

Terminology am I doing a one to many or many to many? Left join? Right?

I need to research this but am confused about the terminology of what I should be researching.
Table1 fields:
salenumber
category
quantity
price
Table2 fields:
field
category
requirement
Table3 fields:
field
salenumber
value
I need to combine these.
Essentially one (salenumber, category, quantity, Price) can have a dynamic number of "fields" containing unique "data associated with it. I'm a little confused as to the terminology of what I am doing here. I'm all mixed up with left and right joins and many to one and many to many databases. If I simply knew the term for what I am trying to do it would help me to narrow down my research.
Joins are for your queries - which you run to find specific records from your database. You aren't there yet. First, you want to do table design, which is where you consider many-to-many and one-to-many relationships.
Start by thinking about what the tables represent. For example, a single sale can involve multiple different products (e.g. you buy a fork, a spoon, a knife, and a new car). Each product can be in a different category (utensils or motor vehicles, in this case). In your table design, you would decide whether a product belongs to only a single category or to multiple categories.
Let's assume there's just one category per product - then you can have many products in one category (fork, spoon and knife are all utensils), but a product can have only one category. In this case, Category to Product is a One-to-Many relationship.
How these connect is where the related fields in tables come in to play - so in the Product table you have 'Category', which refers to the Category table ('Fork' is of Category 'Utensil', and in the Category table 'Utensil' is an entry with additional information).
You probably want to look up some basic database lessons to help you out. There are some good free online classes and resources - just search for info about databases.
This may help understand joins: http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
If you have a row in Table_A with some id, and multiple rows in Table_B related referencing that id you can do a LEFT OUTER JOIN (often just LEFT JOIN). This will match the data in Table_A to Table_B - but you will have as many rows as there were in Table_B!
If you want all of the Table_B data related to the Table_A row in one row result you need an aggregate function. In SQL this is normally something like array_agg. When you do this you need to tell it what to GROUP BY, in my example it would be Table_A.id

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!

Conditional SQL Join using a 3rd table

I've got a problem with an Asset Database that I have been developing for a customer in MSSQL. It entails capturing Required Actions, for example Lifting Equipment at a specific location needs to be inspected 6 months after purchase. The Due Dates for these required actions can be calculated in different ways but to simplify here will be calculated based on their Purchase Date.
So to that end I have a table called tblActionsRequired that contains the following relevant fields:
ActionID - for the action required
EquipmentCategoryID or EquipmentTypeID or EquipmentID - so either one of these fields are required. With this they specify that an action is required for either a category of equipment or an equipment type or a specific piece of equipment. So an example would be that a 2kg Powder Fire Hydrant would be an equipment type, it would fall into the category Fire Safety Equipment and there might be a specific 2kg Powder Fire Hydrant with an asset number of say PFH2KG001.
BasedAtID - the company's branches or sites
Ideally what I'd like to do is keep as much as possible in one query as opposed to creating separate queries or views for every combination and then adding them together using UNIONs. I have several other similar fields by which these required actions can be segmented so it may seem simple enough here to just use unions but I've calculated I would need to cater for 48 different combinations and probably create a View for each and then UNION them together!
So next I have tblEquipment that contains the following relevant keys:
EquipmentID - the primary key
EquipmentTypeID = foreign key, which Equipment Type this asset is a member of
BasedAtID - foreign key, which site the asset is located at
The Equipment Types then belong to Equipment Categories and the Categories then allow building a tree structure with parent-child relationships, but these I think I have sufficiently taken care of in creating a view called vwCategoryTree with the following fields:
ParentCategoryID
EquipmentTypeID
This view has been tested and checks out fine, it cuts through the tree structure and allows you to perform joins between EquipmentTypeID and their ultimate parents with EquipmentCategoryID.
What I need help with is how to do some sort of conditional join between tblActionsRequired and tblEquipment based on which of the fields EquipmentCategoryID, EquipmentTypeID, or EquipmentID have a value. If only EquipmentID or EquipmentTypeID could be specified then I think this would work:
ON (tblActionsRequired.EquipmentID IS NOT NULL AND tblEquipment.EquipmentID = tblActionsRequired.EquipmentID) OR (tblActionsRequired.EquipmentTypeID IS NOT NULL AND tblActionsRequired.EquipmentTypeID = tblEquipment.EquipmentTypeID)
But how do I bring a third table into this join to cater for EquipmentCategoryID or at least avoid having to use a UNION?
Sorry if something doesn't make sense, please just ask! Thank you very much!
One possible approach:
select ...
from tblEquipment e
left join vwCategoryTree c on e.EquipmentTypeID = c.EquipmentTypeID
join tblActionsRequired r
on (e.EquipmentID = r.EquipmentID or
e.EquipmentTypeID = r.EquipmentTypeID or
c.ParentCategoryID = r.EquipmentCategoryID)

Running balance and Database normalization paradigm

Maybe I'm not good in googling but I'm seeking for a set of gold rules and recommendations in designing databases related to billing.
Lets say I have an SQL table with transactions
transactions(id int, credit float, debit float, billable_account_id int)
Based on the rule of database normalization I abandon the idea of storing and updating on every transaction pre-calculated running balance for every *billable_account_id* in the same table or elsewhere regardless of the size of the transaction table.
I'm using Postgres if that matters(though the subject is common) and I'm not an SQL ninja at all but trying to be pedantic in designing.
Questions:
Am I right going with this approach?
If yes, what methods would you suggest in maintaining such table and in composing query for getting running totals?
Any references are very appreciated!
You can use analytic functions to generate a running total in most databases. In Oracle, something like
SELECT billable_account_id,
SUM( (CASE WHEN credit IS NOT NULL THEN credit
WHEN debit IS NOT NULL THEN -1 * debit
ELSE 0
END) ) OVER (PARTITION BY billable_account_id
ORDER BY transaction_date ) running_total
FROM transactions
If you don't have a TRANSACTION_DATE, you could use ID assuming that you can guarantee that the generated IDs are monotonically increasing.
However, from a performance standpoint, you are likely going to want to bend if not break the third normal form normalization rules for OLAP/ DSS type reporting because people are going to want to report on totals pretty frequently and some accounts are likely to have large numbers of transactions. You may, for example, want to create a separate table that has an ending balance for each BILLABLE_ACCOUNT_ID for each month end and then use the analytic function to just add the current month's transactions to last month's ending balance. In Oracle, you may want to create a materialized view that will automatically maintain the running total.