Santa Fe DataBase Solutions is a Sole Proprietorship located in Santa Fe, New Mexico.
SFDBS is exclusively engaged in promoting the use and commercialization of the
Method of Recursive Objects (US Pat 7,548,935).
Santa Fe DataBase Solutions
PATH // www.sfdbs.com > Copy JT to A-L
The Aggregate-Link representation can be used to represent any relationship represented by either the Primary Key / Foreign Key (PKFK) representation or the Junction Table (JT) representation.
In this page, we show by example how JT relationships can be copied into an A-L representation. (See Copying a PKFK Representation to A-L for the corresponding example where the relationship to copy uses the PKFK representation.)
This example uses the JT representation for a Department-Employee relationship and copies it into an equivalent A-L representation. We are using MS SQL Server to perform these steps:
/* mssql.jtDB.createdatabase.1.sql */ /* JT example - creates a database named jtDB. */ use master; go create database jtDB; go /* mssql.jtDB.createobjectandjtrelations.1.sql */ /* Creates object tables for a Department-Employee relationship. */ use jtDB; go create table DEPT ( DEPT_pk char(6) primary key, DEPT_departmentname char(20) not null ); go create table EMP ( EMP_pk char(6) primary key, EMP_employeename char(20) not null ); go create table JNCT ( JNCT_DEPT_fk char(6) not null, JNCT_EMP_fk char(6) not null, primary key(JNCT_DEPT_fk,JNCT_EMP_fk)); go
/* mssql.jtDB.populateobjectandjttables.1.sql */ /* Inserts DEPT (Department, EMP (Employee) object records, JNCT structure records. */ use jtDB; go insert DEPT(DEPT_pk,DEPT_departmentname) values ('DEPT1','Engineering'); go insert DEPT(DEPT_pk,DEPT_departmentname) values ('DEPT2','Marketing'); go insert DEPT(DEPT_pk,DEPT_departmentname) values ('DEPT3','Sales'); go insert DEPT(DEPT_pk,DEPT_departmentname) values ('DEPT4','Personnel'); go insert DEPT(DEPT_pk,DEPT_departmentname) values ('DEPT5','Projects'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP10','John Smith'); go insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT1','EMP10'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP11','Jane Smith'); go insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT2','EMP11'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP12','Joe Smith'); go insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT3','EMP12'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP13','John Brown'); go insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT2','EMP13'); go /* Notice that John Brown in Sales Department as well as Marketing. */ insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT3','EMP13'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP14','Jane Brown'); go insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT1','EMP14'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP15','Joe Brown'); go insert JNCT(JNCT_DEPT_fk,JNCT_EMP_fk) values ('DEPT2','EMP15'); go /* Notice that Employees Jim White and Jack Mills are not assigned Departments. */ insert EMP(EMP_pk,EMP_employeename) values ('EMP16','Jim White'); go insert EMP(EMP_pk,EMP_employeename) values ('EMP17','Jack Mills'); go
Here's what the JT Department-Employee example looks like graphically:
![]() |
/* mssql.jtDB.selectusingjt.1.sql */ /* Selects Department-Employee pairs using JT (excludes childless parents, orphans). */ use jtDB; go select d.DEPT_pk,d.DEPT_departmentname,e.EMP_pk,e.EMP_employeename from DEPT as d inner join JNCT as j on d.DEPT_pk = j.JNCT_DEPT_fk inner join EMP as e on j.JNCT_EMP_fk = e.EMP_pk order by d.DEPT_pk,e.EMP_pk; go
The results of the preceding query:
DEPT_pk | DEPT_departmentname | EMP_pk | EMP_employeename |
---|---|---|---|
DEPT1 | Engineering | EMP10 | John Smith |
DEPT1 | Engineering | EMP14 | Jane Brown |
DEPT2 | Marketing | EMP11 | Jane Smith |
DEPT2 | Marketing | EMP13 | John Brown |
DEPT2 | Marketing | EMP15 | Joe Brown |
DEPT3 | Sales | EMP12 | Joe Smith |
DEPT3 | Sales | EMP13 | John Brown |
By using outer joins, childless parents and/or orphans can be included:
/* mssql.jtDB.selectusingjt.1.sql */ /* Selects Department-Employee pairs using JT (includes childless parents and orphans). */ use jtDB; go select d.DEPT_pk,d.DEPT_departmentname,e.EMP_pk,e.EMP_employeename from DEPT as d left outer join JNCT as j on d.DEPT_pk = j.JNCT_DEPT_fk right outer join EMP as e on j.JNCT_EMP_fk = e.EMP_pk order by d.DEPT_pk,e.EMP_pk; go
The left outer join picks up childless parents (Personnel, Projects). The right outer join picks up orphans (Jim White, Jack Mills).
The results of the preceding query:
DEPT_pk | DEPT_departmentname | EMP_pk | EMP_employeename |
---|---|---|---|
NULL | NULL | EMP16 | Jim White |
NULL | NULL | EMP17 | Jack Mills |
DEPT1 | Engineering | EMP10 | John Smith |
DEPT1 | Engineering | EMP14 | Jane Brown |
DEPT2 | Marketing | EMP11 | Jane Smith |
DEPT2 | Marketing | EMP13 | John Brown |
DEPT2 | Marketing | EMP15 | Joe Brown |
DEPT3 | Sales | EMP12 | Joe Smith |
DEPT3 | Sales | EMP13 | John Brown |
DEPT4 | Personnel | NULL | NULL |
DEPT5 | Projects | NULL | NULL |
In order to create an Aggregate-Link representation, we need to create the Aggregate and Link structure relations. Notice that the integrity constraints on these relations defines a (0,M)-to-(0,M) relationship to match the JT representation.
/* mssql.jtDB.addstructurerelations.1.sql */ /* Adds aggregate and link tables. */ use jtDB; go create table AGG ( AGG_pk integer identity(1,1) primary key, AGG_DEPT_fk char(6) unique ); go create table LNK ( LNK_pk integer identity(1,1) primary key, LNK_AGG_fk integer not null, LNK_EMP_fk char(6) not null ); go
There are several ways to copy from JT to A-L. Here, we copy the childless parents but not the orphans (parentless childs). Below we will account for orphans.
/* mssql.jtDB.copyjttoal.1.sql */ /* Copies JT Department-Employee relationship to A-L (no orphans). */ use jtDB; go insert into AGG(AGG_DEPT_fk) select DEPT_pk from DEPT; go insert into LNK(LNK_AGG_fk,LNK_EMP_fk) select AGG_pk,EMP_pk from AGG as a join JNCT as j on a.AGG_DEPT_fk = j.JNCT_DEPT_fk join EMP as e on j.JNCT_EMP_fk = e.EMP_pk; go
In the first step, this construction creates one aggregate record for each DEPT record. In the second step, it creates one link record for each JT record. (The LNK tuple has LNK_AGG_fk equal to AGG_pk for the AGG tuple with AGG_DEPT_fk equal to JNCT_DEPT_fk.) Childless parents (Personnel, Projects) are included, but not orphans (Jim White, Jack Mills). (See below for SQL queries that account for the orphans.)
/* mssql.jtDB.selectusingal.1.sql */ /* Selects Department-Employee pairs using A-L. */ use jtDB; go select d.DEPT_pk,d.DEPT_departmentname,e.EMP_pk,e.EMP_employeename from DEPT as d right outer join AGG as a on d.DEPT_pk = a.AGG_DEPT_fk left outer join LNK as l on a.AGG_pk = l.LNK_AGG_fk left outer join EMP as e on l.LNK_EMP_fk = e.EMP_pk order by d.DEPT_pk, e.EMP_pk; go
Compare the results (below) of the preceding A-L query to the JT results (above). (Keep in mind that there are no orphans).
DEPT_pk | DEPT_departmentname | EMP_pk | EMP_employeename |
---|---|---|---|
DEPT1 | Engineering | EMP10 | John Smith |
DEPT1 | Engineering | EMP14 | Jane Brown |
DEPT2 | Marketing | EMP11 | Jane Smith |
DEPT2 | Marketing | EMP13 | John Brown |
DEPT2 | Marketing | EMP15 | Joe Brown |
DEPT3 | Sales | EMP12 | Joe Smith |
DEPT3 | Sales | EMP13 | John Brown |
DEPT4 | Personnel | NULL | NULL |
DEPT5 | Projects | NULL | NULL |
As indicated above, the SQL statements "to copy the JT representation to the A-L representation" would omit orphans. To include orphans, we need one more aggregate instance (i.e., an AGG tuple with a NULL valued AGG_DEPT_fk) and an insert/select that inserts LNK tuples for EMP objects not referenced by any JT tuple. LNK_AGG_fk is set to this new AGG tuple's primary key:
/* mssql.jtDB.accountfororphans.1.sql */ /* Copies JT Department-Employee orphans to A-L. */ use jtDB; go insert AGG(AGG_DEPT_fk) values (NULL); go insert LNK(LNK_AGG_fk,LNK_EMP_fk) SELECT a.AGG_pk,e.EMP_pk FROM AGG as a cross join EMP as e WHERE a.AGG_DEPT_fk is null AND e.EMP_pk not in (SELECT l.LNK_EMP_fk FROM LNK as l); go
With a cross join, this is not the most efficient way to account for orphans!
The following table displays the results of the A-L select query (above) after accounting for orphans:
DEPT_pk | DEPT_departmentname | EMP_pk | EMP_employeename |
---|---|---|---|
NULL | NULL | EMP16 | Jim White |
NULL | NULL | EMP17 | Jack Mills |
DEPT1 | Engineering | EMP10 | John Smith |
DEPT1 | Engineering | EMP14 | Jane Brown |
DEPT2 | Marketing | EMP11 | Jane Smith |
DEPT2 | Marketing | EMP13 | John Brown |
DEPT2 | Marketing | EMP15 | Joe Brown |
DEPT3 | Sales | EMP12 | Joe Smith |
DEPT3 | Sales | EMP13 | John Brown |
DEPT4 | Personnel | NULL | NULL |
DEPT5 | Projects | NULL | NULL |
A JT representation of relationship can be copied to an A-L representation with or without childless parent tuples and with or without parentless child tuples (orphans).(See Copying a PKFK Representation to A-L for the corresponding example where the copied relationship uses the PKFK representation.)
Page Content first published: November 13, 2007
Page Content last updated: November 13, 2007