Table keys for SSAS project? - sql-server

I'm creating a very basic cube with the data that I have. This is my scenario; please let me know if I'm approaching this the wrong way.
In our case, there's data in fact table FactSalesDaily that my dim table DimEmp doesn't have, and I want to know what that data is.
I have three tables: FactSalesDaily, DimDate, DimEmp
[FactSalesDaily]
EmpKey DateKey SalesAmount
194 20170125 45.30
195 20170125 21.00
[DimDate]
DateKey FullDate
20170125 01-25-2017
[DimEmp]
EmpKey FullName
194 Joe Smith
As you can see, my fact table has EmpKey 195 that's not part of DimEmp. My understanding is that in the Data Source View Wizard, when I click on Add Related Tables, the wizard will display the related tables based on the foreign keys for fact table FactSalesDaily.
In my particular case, I would like to see the total sales for employee 195. But I can't add a foreign key of FactSalesDaily to DimEmp because 195 doesn't exist.
As a result, Data Source View Wizard will not select DimEmp because there's not relationship between the two tables.
How am I supposed to deal with this issue? I can add a bogus row in DimEmp for all the employees that don't exist, but then I'd have to alter FactSalesDaily by replacing 195 with this bogus row.
Thanks.

Related

Power BI Table Relationship

I am trying to create two relationships between tables in Power BI. I have a table (Observations) that contains an employee_id and a supervisor_id that I am trying to connect to my Contact table.
I need to look up the employee information in the Contact table by using employee_id in the Observation table and also look up the supervisor information in the Contact table using the supervisor_id in the Observation table.
Contact Table Observation Table
=================== =================
Employee_ID Name Position Observation_ID Employee_ID Supervisor_ID
--------------------------------------- ----------------------------------------------
123 John Doe employee 1 123 321
321 Harvey Sample supervisor 2 456 654
456 Mickey Mouse employee 3 456 654
654 Donald Duck supervisor 4 123 321
One possible way is to create two relationships between the observation and contact table:
Create a relationship between Observation Table(Employee_ID) and Contact Table(Employee_ID). The Cardinality should be many to one, and set this relationship as active.
Create a relationship between Observation Table(Supervisor_ID) and Contact Table(Employee_ID). The Cardinality should be many to one, and set this relationship as inactive.
create an inactive relationship Power BI
You will then need to use the DAX USERELATIONSHIP function when you want to use the inactive relationship in a formula. Here is a detailed explanation of how to use USERELATIONSHIP: https://www.sqlbi.com/articles/userelationship-in-calculated-columns/
Alternatively, you can duplicate the contact table and use one copy for the Employee_ID relationship and the other for the Supervisor_ID relationship. Which option is best will depend on your use case.

What's the cleanest way in SQL to break a table into two tables?

I have a table that I want to break into 2 tables. I want to pull some data out of table A, put it into a new table B, and then point each record in A to the corresponding record in the new table.
It's easy enough to populate the new table with an INSERT INTO B blah blah SELECT blah blah FROM A. But the catch is, when I create the new records in B, I want to write the ID of the B record back into A.
I've thought of two ways to do this:
Create a cursor, loop through A a record at a time, create the record in B and post the new ID back to A.
Create a temporary table with the extracted data, an ID for the new record, and the ID of A. Then use this temporary table to populate B and also to post the ID back to A.
Both methods seem cumbersome with a lot of copying all the data back and forth. Is there a clean, simple way to do this or should I just knuckle down and do it the hard way?
Oh, I'm using Microsoft SQL Server, if your answer depends on non-standard features of SQL.
Someone asks for an example. Yes, I should have included something concrete to make it clear. The real example is a bunch of data, but let me give a simplified example of what I mean.
Let's say I have a Customer table with customer_id, name, and city. I want to break city out into a separate table.
So for example:
Customer
ID Name City
17 Al Detroit
22 Betty Baltimore
39 Charles Cleveland
I want to convert this to:
Customer
ID Name City_ID
17 Al 1
22 Betty 2
39 Charles 3
City
ID Name
1 Detroit
2 Baltimore
3 Cleveland
The exact ID values don't matter.
So easy enough to create the City table and the reference ...
create table city (id int identity primary key, name varchar(50))
alter table customer add city_id int references city
And then populate the city table ...
insert into city (name)
select city from customer
The trick is how to get those city IDs back into the Customer table.
(And yes, in this simplified example, the effort may appear pointless. In real life we have many tables with addresses and I want to pull all those fields out of all the other tables and put them into a single address table, so we can standardize the declarations and processing of addresses.)
(Note: I haven't tested the sample code above. Excuse me if there's a typo or something in there.)
You can use the output clause to capture your new ID values.
without any sample data or examples of what you are doing the following is just a guide.
Create a #table to hold the new ID values, then insert the newly inserted Id identity values along with a correlating value from the inserted virtual table. You can then update the original table with the new IDs by joining on this correlating value.
create table #NewIds (TableBId int, TableAId int)
insert into TableB (column list)
output inserted.Id, inserted.TableAId into #NewIds
select column list
from TableA
update a
set a.TableBId=Id
from #NewIds n join TableA a on a.Id=n.TableAId

Creating a global ID for every row in multiple tables for notifications

I'm designing what is essentially an accounting/retailing application for MS SQL Server 2016. I have ~75 core data object types, each in their own respective table (users, organizations, invoices, payments, etc.).
What I need to create is a notification system,
e.g. "Steve paid invoice 1234", "Bob purchased product XYZ", etc. What I was going to create was a "notification types" table:
NotificationTypes:
id message
11 "{0} paid invoice {1]"
12 "{0} purchased product {1]"
...
and then have two corresponding tables that store each notification event's info, and then the values for that notification message. So for example for "Steve paid invoice 1234":
NotificationEvent:
id notificationType (FK) occured
21 11 2016-01-01 00:00:00
NotificationEventValues:
id notificationEvent (FK) XXXXX
31 21 (FK reference to Steve in users table)
32 21 (FK reference to invoice 1234 in invoices table)
Now since I can't create generic foreign keys for NotificationEventValues.XXXXX, I was going to have a single 'dataObjects' table that has FK columns for all 75 data types I have, with only one of the 'data type' columns having a value per row.
This way, every instance of a data object in my database has a unique ID I can reference in the notification field - which will mean a huge table given it has a unique ID for basically every row in the other 75 tables. The other downside is it means for every user, invoice, any 'data object', I'm wasting significant amounts of space since space will be reserved for ID references for the other 74 null-valued columns (since they're fixed size IDs and not variable).
ASK:
Is there a better way to achieve my 'global' identifier across all the tables? Or a better way to handle the notification system to avoid this problem?
Create triggers in all table that will insert a record in a table say KeyMaster with one column key which will also be the primry key whenever a record is inserted in any table. The value inserted in this table will be in the format _. For example if a record is inserted in user table with id 1 then the record inserted in KeyMaster table will be 'user_1'. Similarly if a record is inserted in invoice table with id 1 then the recor inserted in KeyMaster table will be 'invoice_1'.
In your NotificationEventValues table you will need only three columns id,notificationEvent and key (FK reference to KeyMaster table).
For getting corresponding record you need to write query similar to below:
select *
from NotificationEventValues n
inner join users u on 'user_' + u.id = n.key

Tables joined without common fields

I have a SQL Server Database which has 2 tables
Client Table
Name Employment Race
Ronald 867 452
Arnold 845 123
Lookup Table
lookup_id Detail
867 Unemployed
845 Part time employed
452 White
123 Black
The numeric entries point to the primary key of LookUp table called lookup_id. Corresponding to each lookup_id (867,856 etc.) is the actual Employment or Race description in text - Unemployed, White etc. More Client fields follow the same referencing.
However, the lookup_id field by itself does not exist in the Client table. It seems to me that the two tables are linked without a PK,FK reference. Is this possible? Passing a key entry directly into a field to join tables? How do I query these tables together?
You can do that via a query like this.
new query:
SELECT Name, L1.Detail AS Employment, L2.Detail as Race
FROM Client C LEFT OUTER JOIN Lookup L1
ON C.Employment=L1.lookup_id
LEFT OUTER JOIN Lookup L2
ON C.Race=L2.lookup_id
old query:
SELECT Name, Detail
FROM Client C LEFT OUTER JOIN Lookup L
ON C.Employment=L.lookup_id
A FK need not have same name as PK in the FK table, like here Employment and Race columns are foreign key value for Lookup.
Also you should but not necessarily have a FK PK relation defined between tables. This is a common practice in Data warehousing.

SQL JOIN all tables from one data

I am trying to get all the data from all tables in one DB.
I have looked around, but i haven't been able to find any solution that works with my current problems.
I made a C# program that creates a table for each day the program runs. The table name will be like this tbl18_12_2015 for today's date (Danish date format).
Now in order to make a yearly report i would love if i can get ALL the data from all the tables in the DB that stores these reports. I have no way of knowing how many tables there will be or what they are called, other than the format (tblDD-MM-YYYY).
in thinking something like this(that obviously doesen't work)
SELECT * FROM DB_NAME.*
All the tables have the same columns, and one of them is a primary key, that auto increments.
Here is a table named tbl17_12_2015
ID PERSONID NAME PAYMENT TYPE RESULT TYPE
3 92545 TOM 20,5 A NULL NULL
4 92545 TOM 20,5 A NULL NULL
6 117681 LISA NULL NULL 207 R
Here is a table named tbl18_12_2015
ID PERSONID NAME PAYMENT TYPE RESULT TYPE
3 117681 LISA 30 A NULL NULL
4 53694 DAVID 78 A NULL NULL
6 58461 MICHELLE NULL NULL 207 R
What i would like to get is something like this(from all tables in the DB):
PERSONID NAME PAYMENT TYPE RESULT TYPE
92545 TOM 20,5 A NULL NULL
92545 TOM 20,5 A NULL NULL
117681 LISA NULL NULL 207 R
117681 LISA 30 A NULL NULL
53694 DAVID 78 A NULL NULL
58461 MICHELLE NULL NULL 207 R
Have tried some different query's but none of them returned this, just a lot of info about the tables.
Thanks in advance, and happy holidays
edit: corrected tbl18_12_2015 col 3 header to english rather than danish
Thanks to all those who tried to help me solving this question, but i can't (due to my skill set most likely) get the UNION to work, so that's why i decided to refactor my DB.
While you could store the table names in a database and use dynamic sql to union them together, this is NOT a good idea and you shouldn't even consider it - STOP NOW!!!!!
What you need to do is create a new table with the same fields - and add an ID (auto-incrementing identity column) and a DateTime field. Then, instead of creating a new table for each day, just write your data to this table with the DateTime. Then, you can use the DateTime field to filter your results, whether you want something from a day, week, month, year, decade, etc. - and you don't need dynamic sql - and you don't have 10,000 database tables.
I know some people posted comments expressing the same sentiments, but, really, this should be an answer.
If you had all the tables in the same database you would be able to use the UNION Operator to combine all your tables..
Maybe you can do something like this to select all the tables names from a given database
For SQL Server:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='dbName'
For MySQL:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA='dbName'
Once you have the list of tables you can move all the tables to 1 database and create your report using Unions..
You will need to use a UNION between each select query.
Do not use *, always list the name of the columns you are bringing up.
If you want duplicates, then UNION ALL is what you want.
If you want unique records based on the PERSONID, but there is likely to be differences, then I will guess that an UPDATE_DATE column will be useful to determine which one to use but what if each records with the same PERSONID lived a life of its own on each side?
You'd need to determine business rules to find out which specific changes to keep and merge into the unique resulting record and you'd be on your own.
What is "Skyttenavn"? Is it Danish? If it is the same as "NAME", you'd want to alias that column as 'NAME' in the select query, although it's the order of the columns as listed that counts when determining what to unite.
You'd need a new auto-incremented ID as a unique primary key, by the way, if you are likely to have conflicting IDs. If you want to merge them together into a new primary key identity column, you'd want to set IDENTITY_INSERT to OFF then back to ON if you want to restart natural incrementation.

Resources