Copying a JT Representation 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.)

Copying the JT Representation of the Department-Employee Relationship to A-L

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:

  • Create a database (jtDB), define object relations DEPT and EMP and structure relation JNCT.
  • Populate DEPT and EMP object relations and JNCT structure relation.
  • Retrieve all DEPT-EMP pairs using the JT representation (excluding childless parents and orphans).
  • Retrieve all DEPT-EMP pairs using the JT representation (including childless parents and orphans).
  • Define structure relations AGG and LNK for the A-L representation.
  • Use SQL to copy the JT representation to the A-L representation(including childless parents, but no orphans).
  • Retrieve all DEPT-EMP pairs using the A-L representation.
  • Account for the orphans in the JT representation.

Create a database (jtDB), define object relations DEPT and EMP and structure relation JNCT.

/* 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

Populate DEPT and EMP object relations and JNCT structure relation.

/* 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:

Figure 1. Department-Employee Example, JT Representation.

Retrieve all DEPT-EMP pairs using the JT representation (excludes childless parents and orphans).

/* 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:

Table 1. Retrieve DEPT-EMP pairs using JT representation
(excludes childless parents or orhans).
DEPT_pk DEPT_departmentname EMP_pk EMP_employeename
DEPT1EngineeringEMP10John Smith
DEPT1EngineeringEMP14Jane Brown
DEPT2MarketingEMP11Jane Smith
DEPT2MarketingEMP13John Brown
DEPT2MarketingEMP15Joe Brown
DEPT3SalesEMP12Joe Smith
DEPT3SalesEMP13John Brown

By using outer joins, childless parents and/or orphans can be included:

Retrieve all DEPT-EMP pairs using the JT representation (including childless parents and orphans).

/* 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:

Table 2. Retrieve DEPT-EMP pairs using JT representation
(includes childless parents, orphans).
DEPT_pk DEPT_departmentname EMP_pk EMP_employeename
NULLNULLEMP16Jim White
NULLNULLEMP17Jack Mills
DEPT1EngineeringEMP10John Smith
DEPT1EngineeringEMP14Jane Brown
DEPT2MarketingEMP11Jane Smith
DEPT2MarketingEMP13John Brown
DEPT2MarketingEMP15Joe Brown
DEPT3SalesEMP12Joe Smith
DEPT3SalesEMP13John Brown
DEPT4PersonnelNULLNULL
DEPT5ProjectsNULLNULL

Define structure relations AGG and LNK for the A-L representation.

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

Use SQL to copy the JT representation to the A-L representation (including childless parents, but no orphans).

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.)

Retrieve all DEPT-EMP pairs using the A-L representation.

/* 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).

Table 3. Retrieve DEPT-EMP pairs using A-L representation
(includes childless parents, but excludes orphans).
DEPT_pk DEPT_departmentname EMP_pk EMP_employeename
DEPT1EngineeringEMP10John Smith
DEPT1EngineeringEMP14Jane Brown
DEPT2MarketingEMP11Jane Smith
DEPT2MarketingEMP13John Brown
DEPT2MarketingEMP15Joe Brown
DEPT3SalesEMP12Joe Smith
DEPT3SalesEMP13John Brown
DEPT4PersonnelNULLNULL
DEPT5ProjectsNULLNULL

Account for the orphans in the JT representation.

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:

Table 4. Retrieve DEPT-EMP pairs using A-L representation
(includes childless parents and orphans).
DEPT_pk DEPT_departmentname EMP_pk EMP_employeename
NULLNULLEMP16Jim White
NULLNULLEMP17Jack Mills
DEPT1EngineeringEMP10John Smith
DEPT1EngineeringEMP14Jane Brown
DEPT2MarketingEMP11Jane Smith
DEPT2MarketingEMP13John Brown
DEPT2MarketingEMP15Joe Brown
DEPT3SalesEMP12Joe Smith
DEPT3SalesEMP13John Brown
DEPT4PersonnelNULLNULL
DEPT5ProjectsNULLNULL

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