0

I need to perform a complete overhaul of two major systems. Taking a BI perspective, I created some baseline tables, "User", "CRM Details", "Telephony Details" etc.

I have an issue with understanding how relationships are formed between tables.

I dropped a list of users into the "Users" table, and I'll need to do the same into the "Telephony Details" table. How do I build a relationship where it knows 'John Smith' from Users = 'John Smith' in Telephony?

I anticipate the key columns will be "Id" in the Users table and therefore "UserId" in the Telephony table, but how does the UserId end up in the Telephony table?

Code I have so far:

CREATE TABLE Users
(
    Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Forename  NVARCHAR(50),
    Surname   NVARCHAR(50),
    Location  CHAR(50),
    Email     NVARCHAR(320),
    SCD_Start SMALLDATETIME,
    SCD_Stop  SMALLDATETIME,
    IsActive  BIT
)

INSERT INTO Users (Forename,Surname,Location,SCD_Start,SCD_Stop,IsActive)
VALUES ('Test1','Test1','TestL1','2016-11-08',NULL,1)
,('Test2','Test2','TestL2','2016-11-08',NULL,1)
,('Test3','Test3','TestL3','2016-11-08',NULL,1)
,('Test4','Test4','TestL4','2016-11-08',NULL,1)
,('Test5','Test5','TestL5','2016-11-08',NULL,1)
,('Test6','Test6','TestL6','2016-11-08',NULL,1)

CREATE TABLE Telephony
(
    Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Forename    NVARCHAR(50),
    Surname     NVARCHAR(50),
    OfficePhone VARCHAR(22),
    MobilePhone VARCHAR(22),
    SCD_Start   SMALLDATETIME,
    SCD_Stop    SMALLDATETIME,
    IsActive    BIT
)
trincot
  • 317,000
  • 35
  • 244
  • 286
Dan
  • 97
  • 1
  • 7
  • Remove Forename and Surname from Telephony table. That's asking for redundancy and inconsistency. Assuming the Id in the Users table is the uniqueness, use that as a Foreign Key in the Telephony table. Probably rename the Id columns in each table to mean something more (IE. UserId, TelephonyId) – SS_DBA Nov 09 '16 at 20:27
  • Based on prior experience, the Telephony DB can contain a name with slight differences. "Dan" in the Users table and "Daniel" in the Telephony table. With that in mind, should I include them in the Users table as "TelForename" "TelSurname" or some other method? – Dan Nov 09 '16 at 20:28
  • Ah... sorry... forgot you're getting these from different sources. – SS_DBA Nov 09 '16 at 20:30
  • If there's no common uniqueness between the 2 sources, you may not get the relationship between them. – SS_DBA Nov 09 '16 at 20:32
  • Your question is unclear. Please separate 1. how to write queries for when you want u.fname = t.fname and u.sname=t.sname from 2. how to decide whether, given a row from each table, they refer to the same person (or for that matter, two rows in one table) from 3. how to add an id column given the preceding. – philipxy Nov 10 '16 at 22:36

3 Answers3

0

For this particular case, you need to introduce a foreign key in Telephony table referencing Id in Users table.

CREATE TABLE Telephony
        (Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
        UserId int FOREIGN KEY REFERENCES Users(Id)
        Forename    NVARCHAR(50),
        Surname     NVARCHAR(50),
        OfficePhone VARCHAR(22),
        MobilePhone VARCHAR(22),
        SCD_Start   SMALLDATETIME,
        SCD_Stop    SMALLDATETIME,
        IsActive    BIT
)

In general, if you're more familiar with designing software than designing database, it might be a good idea to dig into domain modeling and code first -principles.

JanneP
  • 577
  • 4
  • 12
  • Great, thanks. I am a SAS developer but I also know SQL. Basically I now have to create a Data Mart from scratch. I am not a software, web or other DB designer so my understanding of how this is going to work is only based on how I've seen it operate in large banks. I do understand what your post means, but I still have the question, once I have submitted all colleagues into the "Users" table and start submitting information into the "Telephony" table, how does it 'know' about the UserId information? With this being loaded manually and not through any front-end I think that's my problem. – Dan Nov 09 '16 at 20:33
  • You could get the current identity after the row has been inserted with IDENT_CURRENT('Users'). – JanneP Nov 09 '16 at 20:39
0

Basically, just add another column to Telephony that matches the type (INT) of the Id in Users - call it maybe UserId (often I'll prefix it with "f", fUserId just so a quick glance reminds me it's and FK and not some other value). Then run this command:

alter table Telephony with check add constraint FK_Telephony_UserId foreign key(UserId)
references Users (Id)

Now any records added to Telephony must have a matching UserId. Query using the Users Id value and you'll only get their numbers.

That's it.

Jester
  • 2,728
  • 22
  • 20
  • Thanks for the response. I think I might need to take a step back here - ultimately what I am beginning to realise is, my problem is the method with which I populate these tables. "Users" will be populated by importing data from CSV. "Telephony" of course needs to contain data relevant to the users... So my query here is how do I do that without literally entering the data myself? Is this where a stored proc or something is required so both tables are updated simultaneously? – Dan Nov 09 '16 at 20:37
  • Another method is don't create the FK yet, just the structure and import, tiddy up and make sure IDs match, then declare the FK - that way the constraint doesn't get in your way – Jester Nov 09 '16 at 20:40
  • Ok, so my understanding here is basically do my import via CSV to both tables, let's assume both tables now have 100 people, and luckily nobody has the same name. Each table has a simple Id, and I want to get Id from Users into UserId in Telephony. My question is _how_ do I get that Id to UserId? Do I join the tables specifying the names as a key? Or am I missing something fundamental here, such as each single record loaded into Users must have a parallel load into Telephony, therefor the Id to UserId merge happens automatically? – Dan Nov 09 '16 at 20:44
  • Well, if the names are unique then joining should work. I often have to come up with create solutions when importing from various sources - sometimes its hard to get things to match up ;) – Jester Nov 09 '16 at 20:49
  • So would a legitimate solution be to actually join both tables together and update the UserId field when it's found a matching user? – Dan Nov 09 '16 at 21:00
0

Identification by Name

Presumably in both tables you have

PRIMARY KEY (forename, surname);

You have to decide when a name in a row of Users represents the same person as some row in Telephony. Maybe it's

Users.forename = Telephony.forename AND Users.surname = Telephony.forename

This is a data cleansing/cleaning/scrubbing issue. Anyway, let's say there's a condition ....

A table represents a relationship. If it's a base or metadata table, the DBA/designer tells you the relationship. If it's the result of a query, the query tells you the relationship.

So when you have a query involving two tables and the rows in the tables refer to people by name and you want the people named by two rows to refer to the same people then you add the requirement ... to the query.

Adding ids

We assign unique ids to refer to entities for many reasons. Eg because you don't want to change the many places a name otherwise appears when a person changes their name. Eg so that your queries can involve only an equality on ids instead of multiple columns. Eg so that by using a smaller (integer) identifier rather than a larger (varchar) one you can decrease implementation space (in tables and indexing) and time (in comparisons and indexing) at the expense of increasing implementation space (more tables) and time (more joins). Eg so you can associate many names with the same person. Note that there are tradeoffs for any design decision.

Assuming you want ids: First per SQL Server: how to add new identity column and populate column with ids? add an id column to each table "and the column will be created and automatically populated". If you were starting with tables with no ids:

ALTER TABLE Users ADD Id INT IDENTITY(1,1) PRIMARY KEY
ALTER TABLE Telephony ADD Id INT IDENTITY(1,1) PRIMARY KEY

Then per Update a table using JOIN in SQL Server? set each Telephony id to the User id with the same name per "..." above:

UPDATE t
SET t.Id = u.Id
FROM Users as u
INNER JOIN Telephony as t
WHERE ...

Now you don't need or want names in Telephony:

DROP FORENAME, SURNAME FROM Telephony

Declaring foreign keys

"Relationship" (between tables) is also used for "foreign key constraint". You want a FK from Telephony to Users. You might want ids. But constraints are not needed to query. (The metadata has a table for relationship "there is a fk from table TF column list LF to table TT column list LT", also expressible by "list of values for table TF column list LF appear as lists of values for table TT column list LT".) inal Telephony,

FOREIGN KEY (forename, surname) REFERENCES Users (forename, surname);

For the new tables,

FOREIGN KEY (Id) REFERENCES Users (Id)

PS

A constraint is not actually a relationship, it is an instance of metadata relationship, ie one case of some values that participate in that metadata relationship. It states a fact about the values in base tables. But simultaneously, because each base table holds the rows satisfying some application relationship, it states a fact about every application situation in terms of the application relationships of base tables that it mentions. When table T represents a relationship expressed as E_T, FK constraint tf (c) REFERENCES tt (c) says, "for some values for all other columns, E_tf implies E_tt".

Community
  • 1
  • 1
philipxy
  • 14,867
  • 6
  • 39
  • 83