SSAS Cube Modelling Fact or Dimension - No Additive Columns - sql-server

Im pretty new to BI modelling and have been assigned a project to create a BI solution for a Patient Administration System (millions of rows). There are no sales or additive information in the system. Basically all of the Measures will be Counts. Im finding it difficult to locate good examples/tutorials of the model I require as most BI implementations seem to be based around Sales.
If anyone could help with my modelling problem I would be very grateful.
Tables (columns excluded for brevity) within the implementation are
Patient (
Key -> Surrogate Key
PatientId -> Source System Id
Name -> Text
AgeKey -> FK to Age Dimension Table
NationalityKey -> FK to Nationality Dimension Table
DateOfBirthKey -> FK to Date Dimension Table
GenderKey -> FK to Gender Dimension Table
etc.
)
Referral (
Key -> Surrogate Key
ReferralId -> Source System Id
PatientKey -> FK to PatientTable
ReferredAtDateKey -> FK to Date Dimension Table
PriorityKey -> FK to Priority Dimension Table
SpecialtyKey -> FK to Specialty Dimension Table
etc
)
WaitingList(
Key -> Surrogate Key
WaitingListId -> Source System Id
ReferralKey -> FK to ReferralTable
AddedToListDateKey -> FK to Date Dimension Table
RemovedFromListDateKey -> FK to Date Dimension Table
StatusKey -> FK to Waiting List Status Table
Position -> int
etc
)
I need to be able to build reports/charts around Patients, Referrals and Waiting Lists so I am using Views to create my Fact tables in SSAS. Examples are:
FactPatient (
Key -> Surrogate Key
PatientId -> Source System Id
Name -> Text
AgeKey -> FK to Age Dimension Table
NationalityKey -> FK to Nationality Dimension Table
DateOfBirthKey -> FK to Date Dimension Table
GenderKey -> FK to Gender Dimension Table
etc.
)
FactReferral (
Key -> Surrogate Key
ReferralId -> Source System Id
-- Patient
Name -> Text
AgeKey -> FK to Age Dimension Table
NationalityKey -> FK to Nationality Dimension Table
DateOfBirthKey -> FK to Date Dimension Table
GenderKey -> FK to Gender Dimension Table
etc.
-- Referral
ReferredAtDateKey -> FK to Date Dimension Table
PriorityKey -> FK to Priority Dimension Table
SpecialtyKey -> FK to Specialty Dimension Table
etc
)
FactWaitingList(
Key -> Surrogate Key
WaitingListId -> Source System Id
-- Patient
Name -> Text
AgeKey -> FK to Age Dimension Table
NationalityKey -> FK to Nationality Dimension Table
DateOfBirthKey -> FK to Date Dimension Table
GenderKey -> FK to Gender Dimension Table
etc
-- Referral
ReferredAtDateKey -> FK to Date Dimension Table
PriorityKey -> FK to Priority Dimension Table
SpecialtyKey -> FK to Specialty Dimension Table
etc
-- Waiting List
AddedToListDateKey -> FK to Date Dimension Table
RemovedFromListDateKey -> FK to Date Dimension Table
StatusKey -> FK to Waiting List Status Table
Position -> int
etc
)
As you can see I am attempting to keep to the Star schema here as I am including the Foreign Keys/Relationships to Dimension tables for related objects e.g. FactReferral has all of the FactPatient relationships.
Is this the right way to model this? Or should I be using a Snowflake schema with FactReferral just having a relationship to FactPatient?
Should I create an extra denormalized Dimension for Patient with no relationships and then create a relationship between it and FactReferral? e.g.
DimPatient (
Key -> Surrogate Key
PatientId -> Source System Id
Name -> Text
Age-> int
Nationality -> Text
DateOfBirth -> Date
GenderKey -> Text
etc.
)
FactReferral (
Key -> Surrogate Key
ReferralId -> Source System Id
-- Patient
PatientKey -> FK to Patient Dimension Table
-- Referral
ReferredAtDateKey -> FK to Date Dimension Table
PriorityKey -> FK to Priority Dimension Table
SpecialtyKey -> FK to Specialty Dimension Table
etc
)
Ultimately Im not really sure how to model the one-to-many relationship tree. There are other tables that are related to Referral such as Assessment and Attendance that I have excluded from my description but I have the same problem with.
Any help or suggestions would be most welcome.
Thanks

http://www.sqlservercentral.com/Forums/Topic1728036-17-1.aspx
http://www.sqlservercentral.com/Forums/FindPost1728079.aspx
Answer provided by PB_BI
I don't think that you need a "FactPatient" table in your underlying
data since it looks like it's entirely dimensional. Rather, when it
comes to creating your cube, use the Patient dimension table to create
a measure group that has a factual relationship to the patient
dimension (for counts and such). Then your FactReferral and
FactWaitingList tables will only need to have 1 foreign key to the
Patient dimension (and not all of the patient-specific ones such as
NationalityKey etc.).
I followed the advice and created a denormalized view DimPatients and added this to my data source view. iwas then able to add a relationship to this from FactReferral -> PatientKey.
After this I created a Dimension based on the DimPatients View and was able to add all of the Columns in DimPatients as Attributes for the dimension. This made them Queryable.
The last thing I did was add a Measure Group for the DimPatient dimension which enabled me to perform Queries against the Patient data
Hope this helps someone else some day
Matt

Related

Setting up a many to many relationship. Cube

Can I create a many to many relationship in SSAS in this case:
Recursive table – key, parent_id
Table containing key from the recursive table and key from measures table
Measures table
Steps I take:
Create a cube without the recursive table dimension
Add new measure of counting rows of the bridge table
Add new dimension of the recursive table
When I try to set up Dimension Usage of the Recursive Table to Many to Many with Measures table it tells me that no intermediate measures group or dimension table exists where I have created it in point 2
Links in SSAS:
RecursiveTable --> BridgeTable <-- MeasuresTable
CustomerTable Bridge MeasureTable
Id(PK) CustId(PK) Id (PK)
CustomerId Id CountMeasure
ParentId
DepName

BCNF - Normal Form

Wondering if you think the following table for storing employees in a database would be consider a database in BCNF ?
- Employee Table
Employee_ID (Primary Key, unique)
First_Name
Surname
Religion
Sex
Job Title
Nationality
- Employee_Address Table
Employee_ID (Foreign Key)
Line_One_Address
Line_Two_Address
District
Country
- Employee_Conact Table
Employee_ID (Foreign Key)
Mobile_Number
So my question is do you think this will meet the critria for being in BCNF ? Or should I have a Nationaility table, Job Title Table, Religion table etc. as they will be duplicate information in the db for it
I am just new to the learning normilzation, so any thoughts and tips will be helpful
i would suggest renaming the EMPLOYEE table to PERSON
then you will notice that job title does not belong with the person definiton- so at least that one should be in another table - like a linking table between people and organizations - where you would put the title and hire date etc.

Handling multi-select list in database design

I'm creating a clinic management system where I need to store Medical History for a patient. The user can select multiple history conditions for a single patient, however, each clinic has its own fixed set of Medical History fields.
For example:
Clinic 1:
DiseaseOne
DiseaseTwo
DiseaseThree
Clinic 2:
DiseaseFour
DiseaseFive
DiseaseSize
For my Patient visit in a specific Clinic , the user should be able to check 1 or more Diseases for the patient's medical history based on the clinic type.
I thought of two ways of storing the Medical History data:
First Option:
Add the fields to the corresponding clinic Patient Visit Record:
PatientClinic1VisitRecord:
PatientClinic1VisitRecordId
VisitDate
MedHist_DiseaseOne
MedHist_DiseaseTwo
MedHist_DisearThree
And fill up each MedHist field with the value "True/False" based on the user input.
Second Option:
Have a single MedicalHistory Table that holds all Clinics Medical History detail as well as another table to hold the Patient's medical history in its corresponding visit.
MedicalHistory
ClinicId
MedicalHistoryFieldId
MedicalHistoryFieldName
MedicalHistoryPatientClinicVisit
VisitId
MedicalHistoryFieldId
MedicalHistoryFieldValue
I'm not sure if these approaches are good practices, is a third approach that could be better to use ?
If you only interested on the diseases the person had, then storing the false / non-existing diseases is quite pointless. Not really knowing all the details doesn't help getting the best solution, but I would probably create something like this:
Person:
PersonID
Name
Address
Clinic:
ClinicID
Name
Address
Disease:
DiseaseID
Name
MedicalHistory:
HistoryID (identity, primary key)
PersonID
ClinicID
VisitDate (either date or datetime2 field depending what you need)
DiseaseID
Details, Notes etc
I created this table because my assumption was that people have most likely only 1 disease on 1 visit, so in case there's sometimes several, more rows can be added, instead of creating separate table for the visit, which makes queries most complex.
If you need to track also situation where a disease was checked but result was negative, then new status field is needed for the history table.
If you need to limit which diseases can be entered by which clinic, you'll need separate table for that too.
Create a set of relational tables to get a robust and flexible system, enabling the clinics to add an arbitrary number of diseases, patients, and visits. Also, constructing queries for various group-by criteria will become easier for you.
Build a set of 4 tables plus a Many-to-Many (M2M) "linking" table as given below. The first 3 tables will be less-frequently updated tables. On each visit of a patient to a clinic, add 1 row to the [Visits] table, containing the full detail of the visit EXCEPT disease information. Add 1 row to the M2M [MedicalHistory] table for EACH disease for which the patient will be consulting on that visit.
On a side note - consider using Table-Valued Parameters for passing a number of rows (1 row per disease being consulted) from your front-end program to the SQL Server stored procedure.
Table [Clinics]
ClinicId Primary Key
ClinicName
-more columns -
Table [Diseases]
DiseaseId Primary Key
ClinicId Foreign Key into the [Clinics] table
DiseaseName
- more columns -
Table [Patients]
PatientId Primary Key
ClinicId Foreign Key into the [Clinics] table
PatientName
-more columns -
Table [Visits]
VisitId Primary Key
VisitDate
DoctorId Foreign Key into another table called [Doctor]
BillingAmount
- more columns -
And finally the M2M table: [MedicalHistory]. (Important - All the FK fields should be combined together to form the PK of this table.)
ClinicId Foreign Key into the [Clinics] table
DiseaseId Foreign Key into the [Diseases] table
PatientId Foreign Key into the [Patients] table
VisitId Foreign Key into the [Visits] table

Microsoft Access 2013 - Multiple Foreign Keys in the same Record

I’ve encountered a problem with pulling multiple foreign keys into one record in a Microsoft Access table.
I’ve got two tables with these fields:
Table 1:
Owners
Fields:
Owner ID (Primary Key)
First Name
Last Name
Table 2:
Ships
Fields:
Ship ID (Primary Key)
Ship Name
I need to create a relationship between Table 1 and Table 2 which shows who owns the ship. I’ve tried adding a number field to Table 2 called Owner ID (Foreign Key) and this works absolutely fine.
Working Example:
Table 1 – Owners Table 2 – Ships
Owner ID (Primary Key)__ Ship ID (Primary Key)
First Name \ Ship Name
Last Name \________Owner ID (Foreign Key)
Unfortunately my ships in Table 2 can have multiple owners (up to 5) at the same time. My problem arises when I try to create a series of linking fields in Table 2.
Not Working:
Table 1 – Owners Table 2 – Ships
Owner ID (Primary Key)__ Ship ID (Primary Key)
First Name \ Ship Name
Last Name \ Owner1 ID (Foreign Key)
\______/ Owner2 ID (Foreign Key)
\ Owner3 ID (Foreign Key)
Can anyone recommend any workarounds so I can show multiple owners taken from the Owners table in the Ships table?
Thanks for your help!
Your database design is definitely incorrect.
In the case you explain, you have a many-to-many relationship between Ships and Owners, which MUST translate into a "relationship table" in the relational model.
In this case: a [Ownership] table, with 2 fields, being the 2 Primary Keys (PK) of the related tables.
In other words, you need 3 tables:
Ships(ShipId, ShipName, Whatever) PK is ShipId
Owner(OwnerId, FirstName, LastName) PK is OwnerId
OwnerShip(ShipId, OwnerId) PK is made of the 2 FKs
The problem is that it looks like Access doesn't allow Nullable FK's and so all Owner fields would have to be filled in, no matter how many owners there are.
The only solution to this I can think of is to introduce a ShipOwner table, which has ShipID and OwnerID columns (as FK's to the Ship and Owner tables). You can then have as many Owners as you like.
Pros: You can add things like %Owned if that matters
Cons: The software has to enforce the limit of 5 owners
Biggest Pro: it will work!
Cheers -
EDIT: The first para is wrong: Access does let you add nullable FK's. However I still thing the suggestion here is a good one. Repeating Groups (Owner 1 to 5) is against Normalisation rules, and this suggestion is normalised.

Find efficient way of joining tables

Here is the problem:
We have 3 tables (MS SQL 2008 R2):
Table 1 FILMS (table with films)
Table 2 Songs (table with songs)
Table 3 Titles
Since “Films” and “Songs” can contain more than one title (I have many titles on different languages), I want to keep all of the titles in the separate table “Titles”. Primary keys in tables Films and Songs are based on [int] identity specification with increment +1.
So for example: we can have a film and song with ID=3.
How can I join table “Titles” with “Films” and “Songs”?
P.S. I tried to create unique keys by adding a new column [idKey] with formula to FILMS an SONGS
for Films it was (CONVERT([nvarchar](10),[ID],(0))+'f')
for Songs it was (CONVERT([nvarchar](10),[ID],(0))+'s')
where [ID] is their identity specification
But I wasn’t able to mark this column as a primary key
even if you don't have foreign key constrain in between this three table, you get the the data by joining three table.
SELECT title.*, film.*,songs.*
FROM title t JOIN film f
ON t.title_name = f.title_name
JOIN songs s
ON t.title_name = s.title_name
the point is at-least two table should have a general column

Resources