Advertisement
anchormodeling

Temporal Dimensional Modeling

Feb 19th, 2012
896
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
T-SQL 5.51 KB | None | 0 0
  1. ---------------------------------------------------------------------
  2. -- Temporal Dimensional Modeling (by Lars Rönnbäck)
  3. -- borrowing concepts from Bitemporal Anchor Modeling
  4. -- http://www.anchormodeling.com
  5. --
  6. -- Note that performance could be improved further if
  7. -- paritioning over currently recorded vs erased data
  8. -- is added, but was left out for the sake of making the
  9. -- script runnable on the free SQL Server Express edition.
  10. ---------------------------------------------------------------------
  11.  
  12. ---------------------------------------------------------------------
  13. -- Split dimensions into immutable/mutable parts
  14. -- in order to achieve temporal referential integrity.
  15. -- Add the proper primary key with temporal components.
  16. -- Add a unique constraint ensuring temporal entity integrity.
  17. -- Foreign keys must be declared for table elimination.
  18. ---------------------------------------------------------------------
  19. create table dim1Immutable (
  20.     dim1ID int not null primary key
  21. );
  22. create table dim1Mutable (
  23.     dim1ID int not null foreign key references dim1Immutable(dim1ID),
  24.     dim1Value char(42) not null,
  25.     dim1ChangedAt datetime not null,
  26.     dim1RecordedAt datetime not null,
  27.     dim1ErasedAt datetime not null,
  28.     primary key (
  29.         dim1ID,
  30.         dim1ChangedAt,
  31.         dim1RecordedAt
  32.     ),
  33.     unique (
  34.         dim1ErasedAt,
  35.         dim1ID,
  36.         dim1ChangedAt
  37.     )  
  38. )
  39.  
  40. create table dim2Immutable (
  41.     dim2ID int not null primary key
  42. );
  43. create table dim2Mutable (
  44.     dim2ID int not null foreign key references dim2Immutable(dim2ID),
  45.     dim2Value char(42) not null,
  46.     dim2ChangedAt datetime not null,
  47.     dim2RecordedAt datetime not null,
  48.     dim2ErasedAt datetime not null,
  49.     primary key (
  50.         dim2ID,
  51.         dim2ChangedAt,
  52.         dim2RecordedAt
  53.     )
  54.     unique (
  55.         dim2ErasedAt,
  56.         dim2ID,
  57.         dim2ChangedAt
  58.     )  
  59. )
  60.  
  61. ---------------------------------------------------------------------
  62. -- If nothing references the fact table no immutable part is needed.
  63. -- Add the proper primary key with temporal components.
  64. -- Add a unique constraint ensuring temporal entity integrity.
  65. -- Foreign keys must be declared for table elimination.
  66. ---------------------------------------------------------------------
  67. create table factMutable (
  68.     dim1ID int not null foreign key references dim1Immutable(dim1ID),
  69.     dim2ID int not null foreign key references dim2Immutable(dim2ID),
  70.     measureA money,
  71.     measureB money,
  72.     measureC money,
  73.     factChangedAt datetime not null,
  74.     factRecordedAt datetime not null,
  75.     factErasedAt datetime not null,
  76.     primary key (
  77.         dim1ID,
  78.         dim2ID,
  79.         factChangedAt,
  80.         factRecordedAt
  81.     )
  82.     unique (
  83.         factErasedAt,
  84.         dim1ID,
  85.         dim2ID,
  86.         factChangedAt
  87.     )  
  88. )
  89. go
  90.    
  91. ---------------------------------------------------------------------
  92. -- Create table valued functions that rewind recording time to
  93. -- the given timepoint.
  94. ---------------------------------------------------------------------  
  95. create function rew_dim1Mutable(
  96.     @recordingTimepoint datetime
  97. )
  98. returns table return
  99. select
  100.     *
  101. from
  102.     dim1Mutable
  103. where
  104.     dim1ErasedAt > @recordingTimepoint
  105. and
  106.     dim1RecordedAt <= @recordingTimepoint; 
  107. go
  108.  
  109. create function rew_dim2Mutable(
  110.     @recordingTimepoint datetime
  111. )
  112. returns table return
  113. select
  114.     *
  115. from
  116.     dim2Mutable
  117. where
  118.     dim2ErasedAt > @recordingTimepoint
  119. and
  120.     dim2RecordedAt <= @recordingTimepoint; 
  121. go
  122.  
  123. create function rew_factMutable(
  124.     @recordingTimepoint datetime
  125. )
  126. returns table return
  127. select
  128.     *
  129. from
  130.     factMutable
  131. where
  132.     factErasedAt > @recordingTimepoint
  133. and
  134.     factRecordedAt <= @recordingTimepoint; 
  135. go
  136.  
  137. ---------------------------------------------------------------------
  138. -- Create table valued functions that show information as was
  139. -- at the given timepoints.
  140. ---------------------------------------------------------------------  
  141. create function pit_dim1Mutable(
  142.     @changingTimepoint datetime,
  143.     @recordingTimepoint datetime
  144. )
  145. returns table return
  146. select
  147.     d1m.*
  148. from
  149.     rew_dim1Mutable(@recordingTimepoint) d1m
  150. where
  151.     d1m.dim1ChangedAt = (
  152.         select
  153.             max(sub.dim1ChangedAt)
  154.         from
  155.             rew_dim1Mutable(@recordingTimepoint) sub
  156.         where
  157.             sub.dim1ID = d1m.dim1ID
  158.     );
  159. go 
  160.    
  161. create function pit_dim2Mutable(
  162.     @changingTimepoint datetime,
  163.     @recordingTimepoint datetime
  164. )
  165. returns table return
  166. select
  167.     d2m.*
  168. from
  169.     rew_dim2Mutable(@recordingTimepoint) d2m
  170. where
  171.     d2m.dim2ChangedAt = (
  172.         select
  173.             max(sub.dim2ChangedAt)
  174.         from
  175.             rew_dim2Mutable(@recordingTimepoint) sub
  176.         where
  177.             sub.dim2ID = d2m.dim2ID
  178.     );
  179. go 
  180.  
  181. create function pit_factMutable(
  182.     @changingTimepoint datetime,
  183.     @recordingTimepoint datetime
  184. )
  185. returns table return
  186. select
  187.     fm.*
  188. from
  189.     rew_factMutable(@recordingTimepoint) fm
  190. where
  191.     fm.factChangedAt = (
  192.         select
  193.             max(sub.factChangedAt)
  194.         from
  195.             rew_factMutable(@recordingTimepoint) sub
  196.         where
  197.             sub.dim1ID = fm.dim1ID
  198.         and
  199.             sub.dim2ID = fm.dim2ID
  200.     );
  201. go 
  202.  
  203. ---------------------------------------------------------------------
  204. -- Run a test query, showing that immutable parts are never touched
  205. -- during execution thanks to table elimination.
  206. ---------------------------------------------------------------------  
  207. select
  208.     avg(measureA),
  209.     sum(measureB),
  210.     max(measureC)
  211. from
  212.     pit_factMutable('2001-01-01', '2001-01-01') fm
  213. join
  214.     dim1Immutable d1i
  215. on
  216.     d1i.dim1ID = fm.dim1ID
  217. join
  218.     pit_dim1Mutable('2001-01-01', '2001-01-01') d1m
  219. on
  220.     d1m.dim1ID = d1i.dim1ID
  221. join
  222.     dim2Immutable d2i
  223. on
  224.     d2i.dim2ID = fm.dim2ID
  225. join
  226.     pit_dim2Mutable('2001-01-01', '2001-01-01') d2m
  227. on
  228.     d2m.dim2ID = d2i.dim2ID
  229. where
  230.     d1m.dim1Value = 'Value1'
  231. and
  232.     d2m.dim2Value = 'Value2';
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement