Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. ---------------------------- SETUP DATABASE AND MODEL --------------------------------
  2. USE master;
  3.  
  4. IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'ComplexTest')
  5. BEGIN
  6. ALTER DATABASE ComplexTest SET OFFLINE WITH ROLLBACK IMMEDIATE;
  7. ALTER DATABASE ComplexTest SET ONLINE;
  8. DROP DATABASE ComplexTest
  9. END
  10.  
  11. CREATE DATABASE ComplexTest;
  12.  
  13. USE ComplexTest;
  14.  
  15.  
  16. -------------------------------- [Drop Perspectives] ---------------------------------
  17. -- perspectives are recreated every time the script is run
  18. --------------------------------------------------------------------------------------
  19. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dCO_Company' and type LIKE '%F%')
  20. DROP FUNCTION [dbo].[dCO_Company];
  21. GO
  22. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'pCO_Company' AND type LIKE '%F%')
  23. DROP FUNCTION [dbo].[pCO_Company];
  24. GO
  25. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lCO_Company' AND type LIKE '%V%')
  26. DROP VIEW [dbo].[lCO_Company];
  27. GO
  28. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'llCO_Company')
  29. DROP SYNONYM [dbo].[llCO_Company];
  30. GO
  31. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lpCO_Company' and type LIKE '%F%')
  32. DROP FUNCTION [dbo].[lpCO_Company];
  33. GO
  34. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'plCO_Company')
  35. DROP SYNONYM [dbo].[plCO_Company];
  36. GO
  37. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'ppCO_Company' and type LIKE '%F%')
  38. DROP FUNCTION [dbo].[ppCO_Company];
  39. GO
  40.  
  41. -------------------------------- [Drop Perspectives] ---------------------------------
  42. -- perspectives are recreated every time the script is run
  43. --------------------------------------------------------------------------------------
  44. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dCU_Customer' and type LIKE '%F%')
  45. DROP FUNCTION [dbo].[dCU_Customer];
  46. GO
  47. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'pCU_Customer' AND type LIKE '%F%')
  48. DROP FUNCTION [dbo].[pCU_Customer];
  49. GO
  50. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lCU_Customer' AND type LIKE '%V%')
  51. DROP VIEW [dbo].[lCU_Customer];
  52. GO
  53. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'llCU_Customer')
  54. DROP SYNONYM [dbo].[llCU_Customer];
  55. GO
  56. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lpCU_Customer' and type LIKE '%F%')
  57. DROP FUNCTION [dbo].[lpCU_Customer];
  58. GO
  59. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'plCU_Customer')
  60. DROP SYNONYM [dbo].[plCU_Customer];
  61. GO
  62. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'ppCU_Customer' and type LIKE '%F%')
  63. DROP FUNCTION [dbo].[ppCU_Customer];
  64. GO
  65.  
  66. -------------------------------- [Drop Perspectives] ---------------------------------
  67. -- perspectives are recreated every time the script is run
  68. --------------------------------------------------------------------------------------
  69. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dPO_Position' and type LIKE '%F%')
  70. DROP FUNCTION [dbo].[dPO_Position];
  71. GO
  72. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'pPO_Position' AND type LIKE '%F%')
  73. DROP FUNCTION [dbo].[pPO_Position];
  74. GO
  75. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lPO_Position' AND type LIKE '%V%')
  76. DROP VIEW [dbo].[lPO_Position];
  77. GO
  78. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'llPO_Position')
  79. DROP SYNONYM [dbo].[llPO_Position];
  80. GO
  81. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lpPO_Position' and type LIKE '%F%')
  82. DROP FUNCTION [dbo].[lpPO_Position];
  83. GO
  84. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'plPO_Position')
  85. DROP SYNONYM [dbo].[plPO_Position];
  86. GO
  87. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'ppPO_Position' and type LIKE '%F%')
  88. DROP FUNCTION [dbo].[ppPO_Position];
  89. GO
  90.  
  91. -------------------------------- [Drop Perspectives] ---------------------------------
  92. -- perspectives are recreated every time the script is run
  93. --------------------------------------------------------------------------------------
  94. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dCU_is_PO_holding' and type LIKE '%F%')
  95. DROP FUNCTION [dbo].[dCU_is_PO_holding];
  96. GO
  97. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'pCU_is_PO_holding' AND type LIKE '%F%')
  98. DROP FUNCTION [dbo].[pCU_is_PO_holding];
  99. GO
  100. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lCU_is_PO_holding' AND type LIKE '%V%')
  101. DROP VIEW [dbo].[lCU_is_PO_holding];
  102. GO
  103. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'llCU_is_PO_holding')
  104. DROP SYNONYM [dbo].[llCU_is_PO_holding];
  105. GO
  106. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lpCU_is_PO_holding' and type LIKE '%F%')
  107. DROP FUNCTION [dbo].[lpCU_is_PO_holding];
  108. GO
  109. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'plCU_is_PO_holding')
  110. DROP SYNONYM [dbo].[plCU_is_PO_holding];
  111. GO
  112. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'ppCU_is_PO_holding' and type LIKE '%F%')
  113. DROP FUNCTION [dbo].[ppCU_is_PO_holding];
  114. GO
  115.  
  116. -------------------------------- [Drop Perspectives] ---------------------------------
  117. -- perspectives are recreated every time the script is run
  118. --------------------------------------------------------------------------------------
  119. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dPO_for_CO_the' and type LIKE '%F%')
  120. DROP FUNCTION [dbo].[dPO_for_CO_the];
  121. GO
  122. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'pPO_for_CO_the' AND type LIKE '%F%')
  123. DROP FUNCTION [dbo].[pPO_for_CO_the];
  124. GO
  125. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lPO_for_CO_the' AND type LIKE '%V%')
  126. DROP VIEW [dbo].[lPO_for_CO_the];
  127. GO
  128. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'llPO_for_CO_the')
  129. DROP SYNONYM [dbo].[llPO_for_CO_the];
  130. GO
  131. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'lpPO_for_CO_the' and type LIKE '%F%')
  132. DROP FUNCTION [dbo].[lpPO_for_CO_the];
  133. GO
  134. IF EXISTS (SELECT * FROM sys.synonyms WHERE name = 'plPO_for_CO_the')
  135. DROP SYNONYM [dbo].[plPO_for_CO_the];
  136. GO
  137. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'ppPO_for_CO_the' and type LIKE '%F%')
  138. DROP FUNCTION [dbo].[ppPO_for_CO_the];
  139. GO
  140.  
  141. ----------------------------------- [Knot Table] -------------------------------------
  142. -- TIC_Ticker table
  143. --------------------------------------------------------------------------------------
  144. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'TIC_Ticker' and type LIKE '%U%')
  145. CREATE TABLE [dbo].[TIC_Ticker] (
  146.    TIC_ID smallint not null,
  147.    TIC_Ticker varchar(6) not null,
  148.    constraint pkTIC_Ticker primary key (
  149.       TIC_ID asc
  150.    ),
  151.    constraint uqTIC_Ticker unique (
  152.       TIC_Ticker
  153.    )
  154. );
  155. GO
  156.  
  157. ----------------------------------- [Knot Table] -------------------------------------
  158. -- RAT_Rating table
  159. --------------------------------------------------------------------------------------
  160. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'RAT_Rating' and type LIKE '%U%')
  161. CREATE TABLE [dbo].[RAT_Rating] (
  162.    RAT_ID tinyint not null,
  163.    RAT_Rating char(1) not null,
  164.    constraint pkRAT_Rating primary key (
  165.       RAT_ID asc
  166.    ),
  167.    constraint uqRAT_Rating unique (
  168.       RAT_Rating
  169.    )
  170. );
  171. GO
  172.  
  173. ---------------------------------- [Anchor Table] ------------------------------------
  174. -- CO_Company table (with 1 attributes)
  175. --------------------------------------------------------------------------------------
  176. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'CO_Company' AND type LIKE '%U%')
  177. CREATE TABLE [dbo].[CO_Company] (
  178.    CO_ID int identity(1, 1) not null,
  179.    CO_Dummy bit null,
  180.    constraint pkCO_Company primary key (
  181.       CO_ID asc
  182.    )
  183. );
  184. GO
  185.  
  186. ----------------------- [Key Generation Stored Procedure] ----------------------------
  187. -- CO_Company surrogate key generation stored procedure
  188. --------------------------------------------------------------------------------------
  189. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'kCO_Company' AND type in ('P','PC'))
  190. DROP PROCEDURE [dbo].[kCO_Company]
  191. GO
  192. CREATE PROCEDURE [dbo].[kCO_Company] (
  193.    @requestedNumberOfIdentities bigint
  194. ) AS
  195. BEGIN
  196.    SET NOCOUNT ON;
  197.    IF @requestedNumberOfIdentities > 0
  198.    BEGIN
  199.       WITH rowGenerator (rowNumber) AS (
  200.          SELECT
  201.             1
  202.          UNION ALL
  203.          SELECT
  204.             rowNumber + 1
  205.          FROM
  206.             rowGenerator
  207.          WHERE
  208.             rowNumber < @requestedNumberOfIdentities
  209.       )
  210.       INSERT INTO [dbo].[CO_Company] (CO_Dummy)
  211.       OUTPUT
  212.          inserted.CO_ID
  213.       SELECT
  214.          null
  215.       FROM
  216.          rowGenerator
  217.       OPTION (maxrecursion 0);
  218.    END
  219. END
  220. GO
  221.  
  222. --------------------------------- [Attribute Table] ----------------------------------
  223. -- CO_TIC_Company_Ticker table (on CO_Company)
  224. --------------------------------------------------------------------------------------
  225. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'CO_TIC_Company_Ticker' AND type LIKE '%U%')
  226. CREATE TABLE [dbo].[CO_TIC_Company_Ticker] (
  227.    CO_ID int not null foreign key references [dbo].[CO_Company](CO_ID),
  228.    TIC_ID smallint not null foreign key references [dbo].[TIC_Ticker](TIC_ID),
  229.    CO_TIC_RecordedAt datetime not null,
  230.    CO_TIC_ErasedAt datetime not null,
  231.    constraint uqCO_TIC_Company_Ticker unique (
  232.       CO_TIC_ErasedAt,
  233.       CO_ID
  234.    ),
  235.    constraint pkCO_TIC_Company_Ticker primary key (
  236.       CO_ID asc,
  237.       CO_TIC_RecordedAt desc,
  238.       CO_TIC_ErasedAt desc
  239.    )
  240. ) ON [PRIMARY];
  241. GO
  242.  
  243. -------------------- [All changing currently recorded perspective] -------------------
  244. -- acCO_TIC_Company_Ticker view
  245. --------------------------------------------------------------------------------------
  246. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'acCO_TIC_Company_Ticker' AND type LIKE '%V%')
  247. DROP VIEW [dbo].[acCO_TIC_Company_Ticker];
  248. GO
  249. CREATE VIEW [dbo].[acCO_TIC_Company_Ticker] WITH SCHEMABINDING AS
  250. SELECT
  251.    CO_ID,
  252.    TIC_ID,
  253.    CO_TIC_RecordedAt,
  254.    CO_TIC_ErasedAt
  255. FROM
  256.    [dbo].[CO_TIC_Company_Ticker]
  257. WHERE
  258.    CO_TIC_ErasedAt >= '9999-12-31';
  259. GO
  260.  
  261. --------------------- [All changing rewind recording perspective] --------------------
  262. -- arCO_TIC_Company_Ticker function
  263. --------------------------------------------------------------------------------------
  264. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'arCO_TIC_Company_Ticker' AND type LIKE '%F%')
  265. DROP FUNCTION [dbo].[arCO_TIC_Company_Ticker];
  266. GO
  267. CREATE FUNCTION [dbo].[arCO_TIC_Company_Ticker] (@recordingTimepoint datetime)
  268. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  269. SELECT
  270.    CO_ID,
  271.    TIC_ID,
  272.    CO_TIC_RecordedAt,
  273.    CO_TIC_ErasedAt
  274. FROM
  275.    [dbo].[CO_TIC_Company_Ticker]
  276. WHERE
  277.    CO_TIC_ErasedAt > @recordingTimepoint
  278. AND
  279.    CO_TIC_RecordedAt <= @recordingTimepoint;
  280. GO
  281.  
  282. ------------------------------- [Latest Perspective] ---------------------------------
  283. -- CO_Company viewed as is (given by the latest available information)
  284. --------------------------------------------------------------------------------------
  285. CREATE VIEW [dbo].[lCO_Company] WITH SCHEMABINDING AS
  286. SELECT
  287.    [CO].CO_ID,
  288.    [TIC].TIC_ID,
  289.    [TIC].TIC_Ticker,
  290.    [CO_TIC].CO_TIC_RecordedAt,
  291.    [CO_TIC].CO_TIC_ErasedAt
  292. FROM
  293.    [dbo].[CO_Company] [CO]
  294. LEFT JOIN
  295.    [dbo].[acCO_TIC_Company_Ticker] [CO_TIC]
  296. ON
  297.    [CO_TIC].CO_ID = [CO].CO_ID
  298. LEFT JOIN
  299.    [dbo].[TIC_Ticker] [TIC]
  300. ON
  301.    [TIC].TIC_ID = [CO_TIC].TIC_ID;
  302. GO
  303.  
  304. CREATE SYNONYM [dbo].[llCO_Company] FOR [dbo].[lCO_Company];
  305. GO
  306.  
  307. ----------------- [Latest changing point-in-recording Perspective] -------------------
  308. -- CO_Company viewed as is at the given recording time
  309. --------------------------------------------------------------------------------------
  310. CREATE FUNCTION [dbo].[lpCO_Company] (@recordingTimepoint datetime)
  311. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  312. SELECT
  313.    [CO].CO_ID,
  314.    [TIC].TIC_ID,
  315.    [TIC].TIC_Ticker,
  316.    [CO_TIC].CO_TIC_RecordedAt,
  317.    [CO_TIC].CO_TIC_ErasedAt
  318. FROM
  319.    [dbo].[CO_Company] [CO]
  320. LEFT JOIN
  321.    [dbo].[arCO_TIC_Company_Ticker] (@recordingTimepoint) [CO_TIC]
  322. ON
  323.    [CO_TIC].CO_ID = [CO].CO_ID
  324. LEFT JOIN
  325.    [dbo].[TIC_Ticker] [TIC]
  326. ON
  327.    [TIC].TIC_ID = [CO_TIC].TIC_ID;
  328. GO
  329.  
  330. --------------------------------- [Insert Trigger] -----------------------------------
  331. -- CO_Company insert trigger on the latest perspective
  332. --------------------------------------------------------------------------------------
  333. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'itCO_Company')
  334. DROP TRIGGER [dbo].[itCO_Company]
  335. GO
  336. CREATE TRIGGER [dbo].[itCO_Company] ON lCO_Company
  337. INSTEAD OF INSERT
  338. AS
  339. BEGIN
  340.    SET NOCOUNT ON;
  341.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  342.    DECLARE @CO TABLE (
  343.       Row int identity(1,1) not null primary key,
  344.       CO_ID int not null
  345.    );
  346.    INSERT INTO [dbo].[CO_Company](
  347.       CO_Dummy
  348.    )
  349.    OUTPUT
  350.       inserted.CO_ID
  351.    INTO
  352.       @CO
  353.    SELECT
  354.       null
  355.    FROM
  356.       inserted
  357.    WHERE
  358.       inserted.CO_ID is null;
  359.    INSERT INTO [dbo].[CO_TIC_Company_Ticker](
  360.       CO_ID,
  361.       TIC_ID,
  362.       CO_TIC_RecordedAt,
  363.       CO_TIC_ErasedAt
  364.    )
  365.    SELECT
  366.       ISNULL(i.CO_ID, a.CO_ID),
  367.       k.TIC_ID,
  368.       ISNULL(i.CO_TIC_RecordedAt, @now),
  369.       ISNULL(i.CO_TIC_ErasedAt, '9999-12-31')
  370.    FROM (
  371.       SELECT
  372.          *,
  373.          ROW_NUMBER() OVER (PARTITION BY CO_ID ORDER BY CO_ID) AS Row
  374.       FROM
  375.          inserted
  376.    ) i
  377.    LEFT JOIN
  378.       @CO a
  379.    ON
  380.       a.Row = i.Row
  381.    JOIN
  382.       [dbo].[TIC_Ticker] k
  383.    ON
  384.       k.TIC_Ticker = i.TIC_Ticker
  385.    WHERE
  386.       i.TIC_Ticker is not null;
  387. END
  388. GO
  389.  
  390. --------------------------------- [Update Trigger] -----------------------------------
  391. -- CO_Company update trigger on the latest perspective
  392. --------------------------------------------------------------------------------------
  393. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'utCO_Company')
  394. DROP TRIGGER [dbo].[utCO_Company]
  395. GO
  396. CREATE TRIGGER [dbo].[utCO_Company] ON lCO_Company
  397. INSTEAD OF UPDATE
  398. AS
  399. BEGIN
  400.    SET NOCOUNT ON;
  401.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  402.    IF(UPDATE(CO_ID) OR UPDATE(CO_TIC_RecordedAt))
  403.    RAISERROR('Primary key columns are not updatable.', 16, 1);
  404.    IF(UPDATE(CO_TIC_ErasedAt))
  405.    UPDATE CO_TIC
  406.    SET
  407.       CO_TIC.CO_TIC_ErasedAt = ISNULL(i.CO_TIC_ErasedAt, @now)
  408.    FROM
  409.       [dbo].[CO_TIC_Company_Ticker] CO_TIC
  410.    JOIN
  411.       inserted i
  412.    ON
  413.       i.CO_ID = CO_TIC.CO_ID
  414.    AND
  415.       i.CO_TIC_RecordedAt = CO_TIC.CO_TIC_RecordedAt;
  416.    IF(UPDATE(TIC_Ticker))
  417.    INSERT INTO [dbo].[CO_TIC_Company_Ticker](
  418.       CO_ID,
  419.       TIC_ID,
  420.       CO_TIC_RecordedAt,
  421.       CO_TIC_ErasedAt
  422.    )
  423.    SELECT
  424.       i.CO_ID,
  425.       k.TIC_ID,
  426.       CASE WHEN UPDATE(CO_TIC_ErasedAt) THEN ISNULL(i.CO_TIC_ErasedAt, @now) ELSE @now END,
  427.       '9999-12-31'
  428.    FROM
  429.       inserted i
  430.    JOIN
  431.       [dbo].[TIC_Ticker] k
  432.    ON
  433.       k.TIC_Ticker = i.TIC_Ticker;
  434. END
  435. GO
  436.  
  437. --------------------------------- [Delete Trigger] -----------------------------------
  438. -- CO_Company delete trigger on the latest perspective
  439. --------------------------------------------------------------------------------------
  440. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'dtCO_Company')
  441. DROP TRIGGER [dbo].[dtCO_Company]
  442. GO
  443. CREATE TRIGGER [dbo].[dtCO_Company] ON lCO_Company
  444. INSTEAD OF DELETE
  445. AS
  446. BEGIN
  447.    SET NOCOUNT ON;
  448.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  449.    UPDATE CO_TIC
  450.    SET
  451.       CO_TIC.CO_TIC_ErasedAt = @now
  452.    FROM
  453.       [dbo].[CO_TIC_Company_Ticker] CO_TIC
  454.    JOIN
  455.       deleted d
  456.    ON
  457.       d.CO_ID = CO_TIC.CO_ID
  458.    AND
  459.       d.CO_TIC_RecordedAt = CO_TIC.CO_TIC_RecordedAt;
  460. END
  461. GO
  462.  
  463. ---------------------------- [Point-in-Time Perspective] -----------------------------
  464. -- CO_Company viewed as was (at the given timepoint)
  465. --------------------------------------------------------------------------------------
  466. CREATE FUNCTION [dbo].[pCO_Company] (@changingTimepoint DATETIME2(7))
  467. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  468. SELECT
  469.    [CO].CO_ID,
  470.    [TIC].TIC_ID,
  471.    [TIC].TIC_Ticker,
  472.    [CO_TIC].CO_TIC_RecordedAt,
  473.    [CO_TIC].CO_TIC_ErasedAt
  474. FROM
  475.    [dbo].[CO_Company] [CO]
  476. LEFT JOIN
  477.    [dbo].[acCO_TIC_Company_Ticker] [CO_TIC]
  478. ON
  479.    [CO_TIC].CO_ID = [CO].CO_ID
  480. LEFT JOIN
  481.    [dbo].[TIC_Ticker] [TIC]
  482. ON
  483.    [TIC].TIC_ID = [CO_TIC].TIC_ID;
  484. GO
  485.  
  486. CREATE SYNONYM [dbo].[plCO_Company] FOR [dbo].[pCO_Company];
  487. GO
  488.  
  489. ----------------- [Point-in-changing point-in-recording Perspective] -------------------
  490. -- CO_Company viewed as was (timepoint) at the given recording timepoint
  491. --------------------------------------------------------------------------------------
  492. CREATE FUNCTION [dbo].[ppCO_Company] (@changingTimepoint DATETIME2(7), @recordingTimepoint datetime)
  493. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  494. SELECT
  495.    [CO].CO_ID,
  496.    [TIC].TIC_ID,
  497.    [TIC].TIC_Ticker,
  498.    [CO_TIC].CO_TIC_RecordedAt,
  499.    [CO_TIC].CO_TIC_ErasedAt
  500. FROM
  501.    [dbo].[CO_Company] [CO]
  502. LEFT JOIN
  503.    [dbo].[arCO_TIC_Company_Ticker] (@recordingTimepoint) [CO_TIC]
  504. ON
  505.    [CO_TIC].CO_ID = [CO].CO_ID
  506. LEFT JOIN
  507.    [dbo].[TIC_Ticker] [TIC]
  508. ON
  509.    [TIC].TIC_ID = [CO_TIC].TIC_ID;
  510. GO
  511.  
  512. ---------------------------------- [Anchor Table] ------------------------------------
  513. -- CU_Customer table (with 2 attributes)
  514. --------------------------------------------------------------------------------------
  515. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'CU_Customer' AND type LIKE '%U%')
  516. CREATE TABLE [dbo].[CU_Customer] (
  517.    CU_ID int identity(1, 1) not null,
  518.    CU_Dummy bit null,
  519.    constraint pkCU_Customer primary key (
  520.       CU_ID asc
  521.    )
  522. );
  523. GO
  524.  
  525. ----------------------- [Key Generation Stored Procedure] ----------------------------
  526. -- CU_Customer surrogate key generation stored procedure
  527. --------------------------------------------------------------------------------------
  528. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'kCU_Customer' AND type in ('P','PC'))
  529. DROP PROCEDURE [dbo].[kCU_Customer]
  530. GO
  531. CREATE PROCEDURE [dbo].[kCU_Customer] (
  532.    @requestedNumberOfIdentities bigint
  533. ) AS
  534. BEGIN
  535.    SET NOCOUNT ON;
  536.    IF @requestedNumberOfIdentities > 0
  537.    BEGIN
  538.       WITH rowGenerator (rowNumber) AS (
  539.          SELECT
  540.             1
  541.          UNION ALL
  542.          SELECT
  543.             rowNumber + 1
  544.          FROM
  545.             rowGenerator
  546.          WHERE
  547.             rowNumber < @requestedNumberOfIdentities
  548.       )
  549.       INSERT INTO [dbo].[CU_Customer] (CU_Dummy)
  550.       OUTPUT
  551.          inserted.CU_ID
  552.       SELECT
  553.          null
  554.       FROM
  555.          rowGenerator
  556.       OPTION (maxrecursion 0);
  557.    END
  558. END
  559. GO
  560.  
  561. --------------------------------- [Attribute Table] ----------------------------------
  562. -- CU_RAT_Customer_Rating table (on CU_Customer)
  563. --------------------------------------------------------------------------------------
  564. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'CU_RAT_Customer_Rating' AND type LIKE '%U%')
  565. CREATE TABLE [dbo].[CU_RAT_Customer_Rating] (
  566.    CU_ID int not null foreign key references [dbo].[CU_Customer](CU_ID),
  567.    RAT_ID tinyint not null foreign key references [dbo].[RAT_Rating](RAT_ID),
  568.    CU_RAT_ChangedAt datetime not null,
  569.    CU_RAT_RecordedAt datetime not null,
  570.    CU_RAT_ErasedAt datetime not null,
  571.    constraint uqCU_RAT_Customer_Rating unique (
  572.       CU_RAT_ErasedAt,
  573.       CU_ID,
  574.       CU_RAT_ChangedAt desc
  575.    ),
  576.    constraint pkCU_RAT_Customer_Rating primary key (
  577.       CU_ID asc,
  578.       CU_RAT_ChangedAt desc,
  579.       CU_RAT_RecordedAt desc,
  580.       CU_RAT_ErasedAt desc
  581.    )
  582. ) ON [PRIMARY];
  583. GO
  584.  
  585. -------------------- [All changing currently recorded perspective] -------------------
  586. -- acCU_RAT_Customer_Rating view
  587. --------------------------------------------------------------------------------------
  588. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'acCU_RAT_Customer_Rating' AND type LIKE '%V%')
  589. DROP VIEW [dbo].[acCU_RAT_Customer_Rating];
  590. GO
  591. CREATE VIEW [dbo].[acCU_RAT_Customer_Rating] WITH SCHEMABINDING AS
  592. SELECT
  593.    CU_ID,
  594.    RAT_ID,
  595.    CU_RAT_ChangedAt,
  596.    CU_RAT_RecordedAt,
  597.    CU_RAT_ErasedAt
  598. FROM
  599.    [dbo].[CU_RAT_Customer_Rating]
  600. WHERE
  601.    CU_RAT_ErasedAt >= '9999-12-31';
  602. GO
  603.  
  604. --------------------- [All changing rewind recording perspective] --------------------
  605. -- arCU_RAT_Customer_Rating function
  606. --------------------------------------------------------------------------------------
  607. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'arCU_RAT_Customer_Rating' AND type LIKE '%F%')
  608. DROP FUNCTION [dbo].[arCU_RAT_Customer_Rating];
  609. GO
  610. CREATE FUNCTION [dbo].[arCU_RAT_Customer_Rating] (@recordingTimepoint datetime)
  611. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  612. SELECT
  613.    CU_ID,
  614.    RAT_ID,
  615.    CU_RAT_ChangedAt,
  616.    CU_RAT_RecordedAt,
  617.    CU_RAT_ErasedAt
  618. FROM
  619.    [dbo].[CU_RAT_Customer_Rating]
  620. WHERE
  621.    CU_RAT_ErasedAt > @recordingTimepoint
  622. AND
  623.    CU_RAT_RecordedAt <= @recordingTimepoint;
  624. GO
  625.  
  626. ------------------ [Rewind changing currently recorded perspective] ------------------
  627. -- rcCU_RAT_Customer_Rating function
  628. --------------------------------------------------------------------------------------
  629. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'rcCU_RAT_Customer_Rating' AND type LIKE '%F%')
  630. DROP FUNCTION [dbo].[rcCU_RAT_Customer_Rating];
  631. GO
  632. CREATE FUNCTION [dbo].[rcCU_RAT_Customer_Rating] (@changingTimepoint datetime)
  633. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  634. SELECT
  635.    CU_ID,
  636.    RAT_ID,
  637.    CU_RAT_ChangedAt,
  638.    CU_RAT_RecordedAt,
  639.    CU_RAT_ErasedAt
  640. FROM
  641.    [dbo].[CU_RAT_Customer_Rating]
  642. WHERE
  643.    CU_RAT_ErasedAt >= '9999-12-31'
  644. AND
  645.    CU_RAT_ChangedAt <= @changingTimepoint;
  646. GO
  647.  
  648. ------------------- [Rewind changing rewind recording perspective] -------------------
  649. -- rrCU_RAT_Customer_Rating function
  650. --------------------------------------------------------------------------------------
  651. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'rrCU_RAT_Customer_Rating' AND type LIKE '%F%')
  652. DROP FUNCTION [dbo].[rrCU_RAT_Customer_Rating];
  653. GO
  654. CREATE FUNCTION [dbo].[rrCU_RAT_Customer_Rating] (
  655.    @changingTimepoint datetime,
  656.    @recordingTimepoint datetime
  657. )
  658. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  659. SELECT
  660.    CU_ID,
  661.    RAT_ID,
  662.    CU_RAT_ChangedAt,
  663.    CU_RAT_RecordedAt,
  664.    CU_RAT_ErasedAt
  665. FROM
  666.    [dbo].[CU_RAT_Customer_Rating]
  667. WHERE
  668.    CU_RAT_ErasedAt > @recordingTimepoint
  669. AND
  670.    CU_RAT_ChangedAt <= @changingTimepoint
  671. AND
  672.    CU_RAT_RecordedAt <= @recordingTimepoint;
  673. GO
  674.  
  675. --------------------------------- [Attribute Table] ----------------------------------
  676. -- CU_NAM_Customer_Name table (on CU_Customer)
  677. --------------------------------------------------------------------------------------
  678. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'CU_NAM_Customer_Name' AND type LIKE '%U%')
  679. CREATE TABLE [dbo].[CU_NAM_Customer_Name] (
  680.    CU_ID int not null foreign key references [dbo].[CU_Customer](CU_ID),
  681.    CU_NAM_Customer_Name varchar(42) not null,
  682.    CU_NAM_RecordedAt datetime not null,
  683.    CU_NAM_ErasedAt datetime not null,
  684.    constraint uqCU_NAM_Customer_Name unique (
  685.       CU_NAM_ErasedAt,
  686.       CU_ID
  687.    ),
  688.    constraint pkCU_NAM_Customer_Name primary key (
  689.       CU_ID asc,
  690.       CU_NAM_RecordedAt desc,
  691.       CU_NAM_ErasedAt desc
  692.    )
  693. ) ON [PRIMARY];
  694. GO
  695.  
  696. -------------------- [All changing currently recorded perspective] -------------------
  697. -- acCU_NAM_Customer_Name view
  698. --------------------------------------------------------------------------------------
  699. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'acCU_NAM_Customer_Name' AND type LIKE '%V%')
  700. DROP VIEW [dbo].[acCU_NAM_Customer_Name];
  701. GO
  702. CREATE VIEW [dbo].[acCU_NAM_Customer_Name] WITH SCHEMABINDING AS
  703. SELECT
  704.    CU_ID,
  705.    CU_NAM_Customer_Name,
  706.    CU_NAM_RecordedAt,
  707.    CU_NAM_ErasedAt
  708. FROM
  709.    [dbo].[CU_NAM_Customer_Name]
  710. WHERE
  711.    CU_NAM_ErasedAt >= '9999-12-31';
  712. GO
  713.  
  714. --------------------- [All changing rewind recording perspective] --------------------
  715. -- arCU_NAM_Customer_Name function
  716. --------------------------------------------------------------------------------------
  717. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'arCU_NAM_Customer_Name' AND type LIKE '%F%')
  718. DROP FUNCTION [dbo].[arCU_NAM_Customer_Name];
  719. GO
  720. CREATE FUNCTION [dbo].[arCU_NAM_Customer_Name] (@recordingTimepoint datetime)
  721. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  722. SELECT
  723.    CU_ID,
  724.    CU_NAM_Customer_Name,
  725.    CU_NAM_RecordedAt,
  726.    CU_NAM_ErasedAt
  727. FROM
  728.    [dbo].[CU_NAM_Customer_Name]
  729. WHERE
  730.    CU_NAM_ErasedAt > @recordingTimepoint
  731. AND
  732.    CU_NAM_RecordedAt <= @recordingTimepoint;
  733. GO
  734.  
  735. ------------------------------- [Latest Perspective] ---------------------------------
  736. -- CU_Customer viewed as is (given by the latest available information)
  737. --------------------------------------------------------------------------------------
  738. CREATE VIEW [dbo].[lCU_Customer] WITH SCHEMABINDING AS
  739. SELECT
  740.    [CU].CU_ID,
  741.    [RAT].RAT_ID,
  742.    [RAT].RAT_Rating,
  743.    [CU_RAT].CU_RAT_ChangedAt,
  744.    [CU_RAT].CU_RAT_RecordedAt,
  745.    [CU_RAT].CU_RAT_ErasedAt,
  746.    [CU_NAM].CU_NAM_Customer_Name,
  747.    [CU_NAM].CU_NAM_RecordedAt,
  748.    [CU_NAM].CU_NAM_ErasedAt
  749. FROM
  750.    [dbo].[CU_Customer] [CU]
  751. LEFT JOIN
  752.    [dbo].[acCU_RAT_Customer_Rating] [CU_RAT]
  753. ON
  754.    [CU_RAT].CU_ID = [CU].CU_ID
  755. AND
  756.    [CU_RAT].CU_RAT_ChangedAt = (
  757.       SELECT
  758.          max(sub.CU_RAT_ChangedAt)
  759.       FROM
  760.          [dbo].[acCU_RAT_Customer_Rating] sub
  761.       WHERE
  762.          sub.CU_ID = [CU].CU_ID
  763.    )
  764. LEFT JOIN
  765.    [dbo].[RAT_Rating] [RAT]
  766. ON
  767.    [RAT].RAT_ID = [CU_RAT].RAT_ID
  768. LEFT JOIN
  769.    [dbo].[acCU_NAM_Customer_Name] [CU_NAM]
  770. ON
  771.    [CU_NAM].CU_ID = [CU].CU_ID;
  772. GO
  773.  
  774. CREATE SYNONYM [dbo].[llCU_Customer] FOR [dbo].[lCU_Customer];
  775. GO
  776.  
  777. ----------------- [Latest changing point-in-recording Perspective] -------------------
  778. -- CU_Customer viewed as is at the given recording time
  779. --------------------------------------------------------------------------------------
  780. CREATE FUNCTION [dbo].[lpCU_Customer] (@recordingTimepoint datetime)
  781. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  782. SELECT
  783.    [CU].CU_ID,
  784.    [RAT].RAT_ID,
  785.    [RAT].RAT_Rating,
  786.    [CU_RAT].CU_RAT_ChangedAt,
  787.    [CU_RAT].CU_RAT_RecordedAt,
  788.    [CU_RAT].CU_RAT_ErasedAt,
  789.    [CU_NAM].CU_NAM_Customer_Name,
  790.    [CU_NAM].CU_NAM_RecordedAt,
  791.    [CU_NAM].CU_NAM_ErasedAt
  792. FROM
  793.    [dbo].[CU_Customer] [CU]
  794. LEFT JOIN
  795.    [dbo].[arCU_RAT_Customer_Rating] (@recordingTimepoint) [CU_RAT]
  796. ON
  797.    [CU_RAT].CU_ID = [CU].CU_ID
  798. AND
  799.    [CU_RAT].CU_RAT_ChangedAt = (
  800.       SELECT
  801.          max(sub.CU_RAT_ChangedAt)
  802.       FROM
  803.          [dbo].[arCU_RAT_Customer_Rating] (@recordingTimepoint) sub
  804.       WHERE
  805.          sub.CU_ID = [CU].CU_ID
  806.    )
  807. LEFT JOIN
  808.    [dbo].[RAT_Rating] [RAT]
  809. ON
  810.    [RAT].RAT_ID = [CU_RAT].RAT_ID
  811. LEFT JOIN
  812.    [dbo].[arCU_NAM_Customer_Name] (@recordingTimepoint) [CU_NAM]
  813. ON
  814.    [CU_NAM].CU_ID = [CU].CU_ID;
  815. GO
  816.  
  817. --------------------------------- [Insert Trigger] -----------------------------------
  818. -- CU_Customer insert trigger on the latest perspective
  819. --------------------------------------------------------------------------------------
  820. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'itCU_Customer')
  821. DROP TRIGGER [dbo].[itCU_Customer]
  822. GO
  823. CREATE TRIGGER [dbo].[itCU_Customer] ON lCU_Customer
  824. INSTEAD OF INSERT
  825. AS
  826. BEGIN
  827.    SET NOCOUNT ON;
  828.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  829.    DECLARE @CU TABLE (
  830.       Row int identity(1,1) not null primary key,
  831.       CU_ID int not null
  832.    );
  833.    INSERT INTO [dbo].[CU_Customer](
  834.       CU_Dummy
  835.    )
  836.    OUTPUT
  837.       inserted.CU_ID
  838.    INTO
  839.       @CU
  840.    SELECT
  841.       null
  842.    FROM
  843.       inserted
  844.    WHERE
  845.       inserted.CU_ID is null;
  846.    INSERT INTO [dbo].[CU_RAT_Customer_Rating](
  847.       CU_ID,
  848.       RAT_ID,
  849.       CU_RAT_ChangedAt,
  850.       CU_RAT_RecordedAt,
  851.       CU_RAT_ErasedAt
  852.    )
  853.    SELECT
  854.       ISNULL(i.CU_ID, a.CU_ID),
  855.       k.RAT_ID,
  856.       ISNULL(i.CU_RAT_ChangedAt, @now),
  857.       ISNULL(i.CU_RAT_RecordedAt, @now),
  858.       ISNULL(i.CU_RAT_ErasedAt, '9999-12-31')
  859.    FROM (
  860.       SELECT
  861.          *,
  862.          ROW_NUMBER() OVER (PARTITION BY CU_ID ORDER BY CU_ID) AS Row
  863.       FROM
  864.          inserted
  865.    ) i
  866.    LEFT JOIN
  867.       @CU a
  868.    ON
  869.       a.Row = i.Row
  870.    JOIN
  871.       [dbo].[RAT_Rating] k
  872.    ON
  873.       k.RAT_Rating = i.RAT_Rating
  874.    WHERE
  875.       i.RAT_Rating is not null;
  876.    INSERT INTO [dbo].[CU_NAM_Customer_Name](
  877.       CU_ID,
  878.       CU_NAM_Customer_Name,
  879.       CU_NAM_RecordedAt,
  880.       CU_NAM_ErasedAt
  881.    )
  882.    SELECT
  883.       ISNULL(i.CU_ID, a.CU_ID),
  884.       i.CU_NAM_Customer_Name,
  885.       ISNULL(i.CU_NAM_RecordedAt, @now),
  886.       ISNULL(i.CU_NAM_ErasedAt, '9999-12-31')
  887.    FROM (
  888.       SELECT
  889.          *,
  890.          ROW_NUMBER() OVER (PARTITION BY CU_ID ORDER BY CU_ID) AS Row
  891.       FROM
  892.          inserted
  893.    ) i
  894.    LEFT JOIN
  895.       @CU a
  896.    ON
  897.       a.Row = i.Row
  898.    WHERE
  899.       i.CU_NAM_Customer_Name is not null;
  900. END
  901. GO
  902.  
  903. --------------------------------- [Update Trigger] -----------------------------------
  904. -- CU_Customer update trigger on the latest perspective
  905. --------------------------------------------------------------------------------------
  906. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'utCU_Customer')
  907. DROP TRIGGER [dbo].[utCU_Customer]
  908. GO
  909. CREATE TRIGGER [dbo].[utCU_Customer] ON lCU_Customer
  910. INSTEAD OF UPDATE
  911. AS
  912. BEGIN
  913.    SET NOCOUNT ON;
  914.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  915.    IF(UPDATE(CU_ID) OR UPDATE(CU_RAT_ChangedAt) OR UPDATE(CU_RAT_RecordedAt))
  916.    RAISERROR('Primary key columns are not updatable.', 16, 1);
  917.    IF(UPDATE(CU_RAT_ErasedAt))
  918.    UPDATE CU_RAT
  919.    SET
  920.       CU_RAT.CU_RAT_ErasedAt = ISNULL(i.CU_RAT_ErasedAt, @now)
  921.    FROM
  922.       [dbo].[CU_RAT_Customer_Rating] CU_RAT
  923.    JOIN
  924.       inserted i
  925.    ON
  926.       i.CU_ID = CU_RAT.CU_ID
  927.    AND
  928.       i.CU_RAT_ChangedAt = CU_RAT.CU_RAT_ChangedAt
  929.    AND
  930.       i.CU_RAT_RecordedAt = CU_RAT.CU_RAT_RecordedAt;
  931.    IF(UPDATE(RAT_Rating))
  932.    INSERT INTO [dbo].[CU_RAT_Customer_Rating](
  933.       CU_ID,
  934.       RAT_ID,
  935.       CU_RAT_ChangedAt,
  936.       CU_RAT_RecordedAt,
  937.       CU_RAT_ErasedAt
  938.    )
  939.    SELECT
  940.       i.CU_ID,
  941.       k.RAT_ID,
  942.       CASE WHEN UPDATE(CU_RAT_ErasedAt) THEN i.CU_RAT_ChangedAt ELSE @now END,
  943.       CASE WHEN UPDATE(CU_RAT_ErasedAt) THEN ISNULL(i.CU_RAT_ErasedAt, @now) ELSE @now END,
  944.       '9999-12-31'
  945.    FROM
  946.       inserted i
  947.    JOIN
  948.       [dbo].[RAT_Rating] k
  949.    ON
  950.       k.RAT_Rating = i.RAT_Rating;
  951.    IF(UPDATE(CU_ID) OR UPDATE(CU_NAM_RecordedAt))
  952.    RAISERROR('Primary key columns are not updatable.', 16, 1);
  953.    IF(UPDATE(CU_NAM_ErasedAt))
  954.    UPDATE CU_NAM
  955.    SET
  956.       CU_NAM.CU_NAM_ErasedAt = ISNULL(i.CU_NAM_ErasedAt, @now)
  957.    FROM
  958.       [dbo].[CU_NAM_Customer_Name] CU_NAM
  959.    JOIN
  960.       inserted i
  961.    ON
  962.       i.CU_ID = CU_NAM.CU_ID
  963.    AND
  964.       i.CU_NAM_RecordedAt = CU_NAM.CU_NAM_RecordedAt;
  965.    IF(UPDATE(CU_NAM_Customer_Name))
  966.    INSERT INTO [dbo].[CU_NAM_Customer_Name](
  967.       CU_ID,
  968.       CU_NAM_Customer_Name,
  969.       CU_NAM_RecordedAt,
  970.       CU_NAM_ErasedAt
  971.    )
  972.    SELECT
  973.       i.CU_ID,
  974.       i.CU_NAM_Customer_Name,
  975.       CASE WHEN UPDATE(CU_NAM_ErasedAt) THEN ISNULL(i.CU_NAM_ErasedAt, @now) ELSE @now END,
  976.       '9999-12-31'
  977.    FROM
  978.       inserted i;
  979. END
  980. GO
  981.  
  982. --------------------------------- [Delete Trigger] -----------------------------------
  983. -- CU_Customer delete trigger on the latest perspective
  984. --------------------------------------------------------------------------------------
  985. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'dtCU_Customer')
  986. DROP TRIGGER [dbo].[dtCU_Customer]
  987. GO
  988. CREATE TRIGGER [dbo].[dtCU_Customer] ON lCU_Customer
  989. INSTEAD OF DELETE
  990. AS
  991. BEGIN
  992.    SET NOCOUNT ON;
  993.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  994.    UPDATE CU_RAT
  995.    SET
  996.       CU_RAT.CU_RAT_ErasedAt = @now
  997.    FROM
  998.       [dbo].[CU_RAT_Customer_Rating] CU_RAT
  999.    JOIN
  1000.       deleted d
  1001.    ON
  1002.       d.CU_ID = CU_RAT.CU_ID
  1003.    AND
  1004.       d.CU_RAT_ChangedAt = CU_RAT.CU_RAT_ChangedAt
  1005.    AND
  1006.       d.CU_RAT_RecordedAt = CU_RAT.CU_RAT_RecordedAt;
  1007.    UPDATE CU_NAM
  1008.    SET
  1009.       CU_NAM.CU_NAM_ErasedAt = @now
  1010.    FROM
  1011.       [dbo].[CU_NAM_Customer_Name] CU_NAM
  1012.    JOIN
  1013.       deleted d
  1014.    ON
  1015.       d.CU_ID = CU_NAM.CU_ID
  1016.    AND
  1017.       d.CU_NAM_RecordedAt = CU_NAM.CU_NAM_RecordedAt;
  1018. END
  1019. GO
  1020.  
  1021. ---------------------------- [Point-in-Time Perspective] -----------------------------
  1022. -- CU_Customer viewed as was (at the given timepoint)
  1023. --------------------------------------------------------------------------------------
  1024. CREATE FUNCTION [dbo].[pCU_Customer] (@changingTimepoint DATETIME2(7))
  1025. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1026. SELECT
  1027.    [CU].CU_ID,
  1028.    [RAT].RAT_ID,
  1029.    [RAT].RAT_Rating,
  1030.    [CU_RAT].CU_RAT_ChangedAt,
  1031.    [CU_RAT].CU_RAT_RecordedAt,
  1032.    [CU_RAT].CU_RAT_ErasedAt,
  1033.    [CU_NAM].CU_NAM_Customer_Name,
  1034.    [CU_NAM].CU_NAM_RecordedAt,
  1035.    [CU_NAM].CU_NAM_ErasedAt
  1036. FROM
  1037.    [dbo].[CU_Customer] [CU]
  1038. LEFT JOIN
  1039.    [dbo].[rcCU_RAT_Customer_Rating] (@changingTimepoint) [CU_RAT]
  1040. ON
  1041.    [CU_RAT].CU_ID = [CU].CU_ID
  1042. AND
  1043.    [CU_RAT].CU_RAT_ChangedAt = (
  1044.       SELECT
  1045.          max(sub.CU_RAT_ChangedAt)
  1046.       FROM
  1047.          [dbo].[rcCU_RAT_Customer_Rating] (@changingTimepoint) sub
  1048.       WHERE
  1049.          sub.CU_ID = [CU].CU_ID
  1050.    )
  1051. LEFT JOIN
  1052.    [dbo].[RAT_Rating] [RAT]
  1053. ON
  1054.    [RAT].RAT_ID = [CU_RAT].RAT_ID
  1055. LEFT JOIN
  1056.    [dbo].[acCU_NAM_Customer_Name] [CU_NAM]
  1057. ON
  1058.    [CU_NAM].CU_ID = [CU].CU_ID;
  1059. GO
  1060.  
  1061. CREATE SYNONYM [dbo].[plCU_Customer] FOR [dbo].[pCU_Customer];
  1062. GO
  1063.  
  1064. ----------------- [Point-in-changing point-in-recording Perspective] -------------------
  1065. -- CU_Customer viewed as was (timepoint) at the given recording timepoint
  1066. --------------------------------------------------------------------------------------
  1067. CREATE FUNCTION [dbo].[ppCU_Customer] (@changingTimepoint DATETIME2(7), @recordingTimepoint datetime)
  1068. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1069. SELECT
  1070.    [CU].CU_ID,
  1071.    [RAT].RAT_ID,
  1072.    [RAT].RAT_Rating,
  1073.    [CU_RAT].CU_RAT_ChangedAt,
  1074.    [CU_RAT].CU_RAT_RecordedAt,
  1075.    [CU_RAT].CU_RAT_ErasedAt,
  1076.    [CU_NAM].CU_NAM_Customer_Name,
  1077.    [CU_NAM].CU_NAM_RecordedAt,
  1078.    [CU_NAM].CU_NAM_ErasedAt
  1079. FROM
  1080.    [dbo].[CU_Customer] [CU]
  1081. LEFT JOIN
  1082.    [dbo].[rrCU_RAT_Customer_Rating] (@changingTimepoint, @recordingTimepoint) [CU_RAT]
  1083. ON
  1084.    [CU_RAT].CU_ID = [CU].CU_ID
  1085. AND
  1086.    [CU_RAT].CU_RAT_ChangedAt = (
  1087.       SELECT
  1088.          max(sub.CU_RAT_ChangedAt)
  1089.       FROM
  1090.          [dbo].[rrCU_RAT_Customer_Rating] (@changingTimepoint, @recordingTimepoint) sub
  1091.       WHERE
  1092.          sub.CU_ID = [CU].CU_ID
  1093.    )
  1094. LEFT JOIN
  1095.    [dbo].[RAT_Rating] [RAT]
  1096. ON
  1097.    [RAT].RAT_ID = [CU_RAT].RAT_ID
  1098. LEFT JOIN
  1099.    [dbo].[arCU_NAM_Customer_Name] (@recordingTimepoint) [CU_NAM]
  1100. ON
  1101.    [CU_NAM].CU_ID = [CU].CU_ID;
  1102. GO
  1103.  
  1104. ------------------------------ [Difference Perspective] ------------------------------
  1105. -- CU_Customer viewed by differences in CU_RAT_Customer_Rating
  1106. --------------------------------------------------------------------------------------
  1107. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dCU_RAT_Customer_Rating' AND type LIKE '%F%')
  1108. DROP FUNCTION [dbo].[dCU_RAT_Customer_Rating];
  1109. GO
  1110. CREATE FUNCTION [dbo].[dCU_RAT_Customer_Rating] (@intervalStart DATETIME2(7), @intervalEnd DATETIME2(7))
  1111. RETURNS TABLE AS RETURN
  1112. SELECT
  1113.    timepoints.inspectedTimepoint,
  1114.    [CU].*
  1115. FROM (
  1116.    SELECT DISTINCT
  1117.       CU_RAT_ChangedAt AS inspectedTimepoint
  1118.    FROM
  1119.       [dbo].[CU_RAT_Customer_Rating]
  1120.    WHERE
  1121.       CU_RAT_ChangedAt BETWEEN @intervalStart AND @intervalEnd
  1122. ) timepoints
  1123. CROSS APPLY
  1124.    pCU_Customer(timepoints.inspectedTimepoint) [CU];
  1125. GO
  1126.  
  1127. ------------------------------ [Difference Perspective] ------------------------------
  1128. -- CU_Customer viewed by differences in every historized attribute
  1129. --------------------------------------------------------------------------------------
  1130. CREATE FUNCTION [dbo].[dCU_Customer] (@intervalStart DATETIME2(7), @intervalEnd DATETIME2(7))
  1131. RETURNS TABLE AS RETURN
  1132. SELECT
  1133.    timepoints.inspectedTimepoint,
  1134.    [CU].*
  1135. FROM (
  1136.    SELECT DISTINCT
  1137.       CU_RAT_ChangedAt AS inspectedTimepoint
  1138.    FROM
  1139.       [dbo].[CU_RAT_Customer_Rating]
  1140.    WHERE
  1141.       CU_RAT_ChangedAt BETWEEN @intervalStart AND @intervalEnd
  1142. ) timepoints
  1143. CROSS APPLY
  1144.    [dbo].[pCU_Customer](timepoints.inspectedTimepoint) [CU];
  1145. GO
  1146.  
  1147. ---------------------------------- [Anchor Table] ------------------------------------
  1148. -- PO_Position table (with 1 attributes)
  1149. --------------------------------------------------------------------------------------
  1150. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'PO_Position' AND type LIKE '%U%')
  1151. CREATE TABLE [dbo].[PO_Position] (
  1152.    PO_ID int identity(1, 1) not null,
  1153.    PO_Dummy bit null,
  1154.    constraint pkPO_Position primary key (
  1155.       PO_ID asc
  1156.    )
  1157. );
  1158. GO
  1159.  
  1160. ----------------------- [Key Generation Stored Procedure] ----------------------------
  1161. -- PO_Position surrogate key generation stored procedure
  1162. --------------------------------------------------------------------------------------
  1163. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'kPO_Position' AND type in ('P','PC'))
  1164. DROP PROCEDURE [dbo].[kPO_Position]
  1165. GO
  1166. CREATE PROCEDURE [dbo].[kPO_Position] (
  1167.    @requestedNumberOfIdentities bigint
  1168. ) AS
  1169. BEGIN
  1170.    SET NOCOUNT ON;
  1171.    IF @requestedNumberOfIdentities > 0
  1172.    BEGIN
  1173.       WITH rowGenerator (rowNumber) AS (
  1174.          SELECT
  1175.             1
  1176.          UNION ALL
  1177.          SELECT
  1178.             rowNumber + 1
  1179.          FROM
  1180.             rowGenerator
  1181.          WHERE
  1182.             rowNumber < @requestedNumberOfIdentities
  1183.       )
  1184.       INSERT INTO [dbo].[PO_Position] (PO_Dummy)
  1185.       OUTPUT
  1186.          inserted.PO_ID
  1187.       SELECT
  1188.          null
  1189.       FROM
  1190.          rowGenerator
  1191.       OPTION (maxrecursion 0);
  1192.    END
  1193. END
  1194. GO
  1195.  
  1196. --------------------------------- [Attribute Table] ----------------------------------
  1197. -- PO_QUA_Position_Quantity table (on PO_Position)
  1198. --------------------------------------------------------------------------------------
  1199. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'PO_QUA_Position_Quantity' AND type LIKE '%U%')
  1200. CREATE TABLE [dbo].[PO_QUA_Position_Quantity] (
  1201.    PO_ID int not null foreign key references [dbo].[PO_Position](PO_ID),
  1202.    PO_QUA_Position_Quantity int not null,
  1203.    PO_QUA_ChangedAt datetime not null,
  1204.    PO_QUA_RecordedAt datetime not null,
  1205.    PO_QUA_ErasedAt datetime not null,
  1206.    constraint uqPO_QUA_Position_Quantity unique (
  1207.       PO_QUA_ErasedAt,
  1208.       PO_ID,
  1209.       PO_QUA_ChangedAt desc
  1210.    ),
  1211.    constraint pkPO_QUA_Position_Quantity primary key (
  1212.       PO_ID asc,
  1213.       PO_QUA_ChangedAt desc,
  1214.       PO_QUA_RecordedAt desc,
  1215.       PO_QUA_ErasedAt desc
  1216.    )
  1217. ) ON [PRIMARY];
  1218. GO
  1219.  
  1220. -------------------- [All changing currently recorded perspective] -------------------
  1221. -- acPO_QUA_Position_Quantity view
  1222. --------------------------------------------------------------------------------------
  1223. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'acPO_QUA_Position_Quantity' AND type LIKE '%V%')
  1224. DROP VIEW [dbo].[acPO_QUA_Position_Quantity];
  1225. GO
  1226. CREATE VIEW [dbo].[acPO_QUA_Position_Quantity] WITH SCHEMABINDING AS
  1227. SELECT
  1228.    PO_ID,
  1229.    PO_QUA_Position_Quantity,
  1230.    PO_QUA_ChangedAt,
  1231.    PO_QUA_RecordedAt,
  1232.    PO_QUA_ErasedAt
  1233. FROM
  1234.    [dbo].[PO_QUA_Position_Quantity]
  1235. WHERE
  1236.    PO_QUA_ErasedAt >= '9999-12-31';
  1237. GO
  1238.  
  1239. --------------------- [All changing rewind recording perspective] --------------------
  1240. -- arPO_QUA_Position_Quantity function
  1241. --------------------------------------------------------------------------------------
  1242. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'arPO_QUA_Position_Quantity' AND type LIKE '%F%')
  1243. DROP FUNCTION [dbo].[arPO_QUA_Position_Quantity];
  1244. GO
  1245. CREATE FUNCTION [dbo].[arPO_QUA_Position_Quantity] (@recordingTimepoint datetime)
  1246. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1247. SELECT
  1248.    PO_ID,
  1249.    PO_QUA_Position_Quantity,
  1250.    PO_QUA_ChangedAt,
  1251.    PO_QUA_RecordedAt,
  1252.    PO_QUA_ErasedAt
  1253. FROM
  1254.    [dbo].[PO_QUA_Position_Quantity]
  1255. WHERE
  1256.    PO_QUA_ErasedAt > @recordingTimepoint
  1257. AND
  1258.    PO_QUA_RecordedAt <= @recordingTimepoint;
  1259. GO
  1260.  
  1261. ------------------ [Rewind changing currently recorded perspective] ------------------
  1262. -- rcPO_QUA_Position_Quantity function
  1263. --------------------------------------------------------------------------------------
  1264. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'rcPO_QUA_Position_Quantity' AND type LIKE '%F%')
  1265. DROP FUNCTION [dbo].[rcPO_QUA_Position_Quantity];
  1266. GO
  1267. CREATE FUNCTION [dbo].[rcPO_QUA_Position_Quantity] (@changingTimepoint datetime)
  1268. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1269. SELECT
  1270.    PO_ID,
  1271.    PO_QUA_Position_Quantity,
  1272.    PO_QUA_ChangedAt,
  1273.    PO_QUA_RecordedAt,
  1274.    PO_QUA_ErasedAt
  1275. FROM
  1276.    [dbo].[PO_QUA_Position_Quantity]
  1277. WHERE
  1278.    PO_QUA_ErasedAt >= '9999-12-31'
  1279. AND
  1280.    PO_QUA_ChangedAt <= @changingTimepoint;
  1281. GO
  1282.  
  1283. ------------------- [Rewind changing rewind recording perspective] -------------------
  1284. -- rrPO_QUA_Position_Quantity function
  1285. --------------------------------------------------------------------------------------
  1286. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'rrPO_QUA_Position_Quantity' AND type LIKE '%F%')
  1287. DROP FUNCTION [dbo].[rrPO_QUA_Position_Quantity];
  1288. GO
  1289. CREATE FUNCTION [dbo].[rrPO_QUA_Position_Quantity] (
  1290.    @changingTimepoint datetime,
  1291.    @recordingTimepoint datetime
  1292. )
  1293. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1294. SELECT
  1295.    PO_ID,
  1296.    PO_QUA_Position_Quantity,
  1297.    PO_QUA_ChangedAt,
  1298.    PO_QUA_RecordedAt,
  1299.    PO_QUA_ErasedAt
  1300. FROM
  1301.    [dbo].[PO_QUA_Position_Quantity]
  1302. WHERE
  1303.    PO_QUA_ErasedAt > @recordingTimepoint
  1304. AND
  1305.    PO_QUA_ChangedAt <= @changingTimepoint
  1306. AND
  1307.    PO_QUA_RecordedAt <= @recordingTimepoint;
  1308. GO
  1309.  
  1310. ------------------------------- [Latest Perspective] ---------------------------------
  1311. -- PO_Position viewed as is (given by the latest available information)
  1312. --------------------------------------------------------------------------------------
  1313. CREATE VIEW [dbo].[lPO_Position] WITH SCHEMABINDING AS
  1314. SELECT
  1315.    [PO].PO_ID,
  1316.    [PO_QUA].PO_QUA_Position_Quantity,
  1317.    [PO_QUA].PO_QUA_ChangedAt,
  1318.    [PO_QUA].PO_QUA_RecordedAt,
  1319.    [PO_QUA].PO_QUA_ErasedAt
  1320. FROM
  1321.    [dbo].[PO_Position] [PO]
  1322. LEFT JOIN
  1323.    [dbo].[acPO_QUA_Position_Quantity] [PO_QUA]
  1324. ON
  1325.    [PO_QUA].PO_ID = [PO].PO_ID
  1326. AND
  1327.    [PO_QUA].PO_QUA_ChangedAt = (
  1328.       SELECT
  1329.          max(sub.PO_QUA_ChangedAt)
  1330.       FROM
  1331.          [dbo].[acPO_QUA_Position_Quantity] sub
  1332.       WHERE
  1333.          sub.PO_ID = [PO].PO_ID
  1334.    );
  1335. GO
  1336.  
  1337. CREATE SYNONYM [dbo].[llPO_Position] FOR [dbo].[lPO_Position];
  1338. GO
  1339.  
  1340. ----------------- [Latest changing point-in-recording Perspective] -------------------
  1341. -- PO_Position viewed as is at the given recording time
  1342. --------------------------------------------------------------------------------------
  1343. CREATE FUNCTION [dbo].[lpPO_Position] (@recordingTimepoint datetime)
  1344. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1345. SELECT
  1346.    [PO].PO_ID,
  1347.    [PO_QUA].PO_QUA_Position_Quantity,
  1348.    [PO_QUA].PO_QUA_ChangedAt,
  1349.    [PO_QUA].PO_QUA_RecordedAt,
  1350.    [PO_QUA].PO_QUA_ErasedAt
  1351. FROM
  1352.    [dbo].[PO_Position] [PO]
  1353. LEFT JOIN
  1354.    [dbo].[arPO_QUA_Position_Quantity] (@recordingTimepoint) [PO_QUA]
  1355. ON
  1356.    [PO_QUA].PO_ID = [PO].PO_ID
  1357. AND
  1358.    [PO_QUA].PO_QUA_ChangedAt = (
  1359.       SELECT
  1360.          max(sub.PO_QUA_ChangedAt)
  1361.       FROM
  1362.          [dbo].[arPO_QUA_Position_Quantity] (@recordingTimepoint) sub
  1363.       WHERE
  1364.          sub.PO_ID = [PO].PO_ID
  1365.    );
  1366. GO
  1367.  
  1368. --------------------------------- [Insert Trigger] -----------------------------------
  1369. -- PO_Position insert trigger on the latest perspective
  1370. --------------------------------------------------------------------------------------
  1371. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'itPO_Position')
  1372. DROP TRIGGER [dbo].[itPO_Position]
  1373. GO
  1374. CREATE TRIGGER [dbo].[itPO_Position] ON lPO_Position
  1375. INSTEAD OF INSERT
  1376. AS
  1377. BEGIN
  1378.    SET NOCOUNT ON;
  1379.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  1380.    DECLARE @PO TABLE (
  1381.       Row int identity(1,1) not null primary key,
  1382.       PO_ID int not null
  1383.    );
  1384.    INSERT INTO [dbo].[PO_Position](
  1385.       PO_Dummy
  1386.    )
  1387.    OUTPUT
  1388.       inserted.PO_ID
  1389.    INTO
  1390.       @PO
  1391.    SELECT
  1392.       null
  1393.    FROM
  1394.       inserted
  1395.    WHERE
  1396.       inserted.PO_ID is null;
  1397.    INSERT INTO [dbo].[PO_QUA_Position_Quantity](
  1398.       PO_ID,
  1399.       PO_QUA_Position_Quantity,
  1400.       PO_QUA_ChangedAt,
  1401.       PO_QUA_RecordedAt,
  1402.       PO_QUA_ErasedAt
  1403.    )
  1404.    SELECT
  1405.       ISNULL(i.PO_ID, a.PO_ID),
  1406.       i.PO_QUA_Position_Quantity,
  1407.       ISNULL(i.PO_QUA_ChangedAt, @now),
  1408.       ISNULL(i.PO_QUA_RecordedAt, @now),
  1409.       ISNULL(i.PO_QUA_ErasedAt, '9999-12-31')
  1410.    FROM (
  1411.       SELECT
  1412.          *,
  1413.          ROW_NUMBER() OVER (PARTITION BY PO_ID ORDER BY PO_ID) AS Row
  1414.       FROM
  1415.          inserted
  1416.    ) i
  1417.    LEFT JOIN
  1418.       @PO a
  1419.    ON
  1420.       a.Row = i.Row
  1421.    WHERE
  1422.       i.PO_QUA_Position_Quantity is not null;
  1423. END
  1424. GO
  1425.  
  1426. --------------------------------- [Update Trigger] -----------------------------------
  1427. -- PO_Position update trigger on the latest perspective
  1428. --------------------------------------------------------------------------------------
  1429. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'utPO_Position')
  1430. DROP TRIGGER [dbo].[utPO_Position]
  1431. GO
  1432. CREATE TRIGGER [dbo].[utPO_Position] ON lPO_Position
  1433. INSTEAD OF UPDATE
  1434. AS
  1435. BEGIN
  1436.    SET NOCOUNT ON;
  1437.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  1438.    IF(UPDATE(PO_ID) OR UPDATE(PO_QUA_ChangedAt) OR UPDATE(PO_QUA_RecordedAt))
  1439.    RAISERROR('Primary key columns are not updatable.', 16, 1);
  1440.    IF(UPDATE(PO_QUA_ErasedAt))
  1441.    UPDATE PO_QUA
  1442.    SET
  1443.       PO_QUA.PO_QUA_ErasedAt = ISNULL(i.PO_QUA_ErasedAt, @now)
  1444.    FROM
  1445.       [dbo].[PO_QUA_Position_Quantity] PO_QUA
  1446.    JOIN
  1447.       inserted i
  1448.    ON
  1449.       i.PO_ID = PO_QUA.PO_ID
  1450.    AND
  1451.       i.PO_QUA_ChangedAt = PO_QUA.PO_QUA_ChangedAt
  1452.    AND
  1453.       i.PO_QUA_RecordedAt = PO_QUA.PO_QUA_RecordedAt;
  1454.    IF(UPDATE(PO_QUA_Position_Quantity))
  1455.    INSERT INTO [dbo].[PO_QUA_Position_Quantity](
  1456.       PO_ID,
  1457.       PO_QUA_Position_Quantity,
  1458.       PO_QUA_ChangedAt,
  1459.       PO_QUA_RecordedAt,
  1460.       PO_QUA_ErasedAt
  1461.    )
  1462.    SELECT
  1463.       i.PO_ID,
  1464.       i.PO_QUA_Position_Quantity,
  1465.       CASE WHEN UPDATE(PO_QUA_ErasedAt) THEN i.PO_QUA_ChangedAt ELSE @now END,
  1466.       CASE WHEN UPDATE(PO_QUA_ErasedAt) THEN ISNULL(i.PO_QUA_ErasedAt, @now) ELSE @now END,
  1467.       '9999-12-31'
  1468.    FROM
  1469.       inserted i;
  1470. END
  1471. GO
  1472.  
  1473. --------------------------------- [Delete Trigger] -----------------------------------
  1474. -- PO_Position delete trigger on the latest perspective
  1475. --------------------------------------------------------------------------------------
  1476. IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'dtPO_Position')
  1477. DROP TRIGGER [dbo].[dtPO_Position]
  1478. GO
  1479. CREATE TRIGGER [dbo].[dtPO_Position] ON lPO_Position
  1480. INSTEAD OF DELETE
  1481. AS
  1482. BEGIN
  1483.    SET NOCOUNT ON;
  1484.    DECLARE @now DATETIME2(7) = SYSDATETIME();
  1485.    UPDATE PO_QUA
  1486.    SET
  1487.       PO_QUA.PO_QUA_ErasedAt = @now
  1488.    FROM
  1489.       [dbo].[PO_QUA_Position_Quantity] PO_QUA
  1490.    JOIN
  1491.       deleted d
  1492.    ON
  1493.       d.PO_ID = PO_QUA.PO_ID
  1494.    AND
  1495.       d.PO_QUA_ChangedAt = PO_QUA.PO_QUA_ChangedAt
  1496.    AND
  1497.       d.PO_QUA_RecordedAt = PO_QUA.PO_QUA_RecordedAt;
  1498. END
  1499. GO
  1500.  
  1501. ---------------------------- [Point-in-Time Perspective] -----------------------------
  1502. -- PO_Position viewed as was (at the given timepoint)
  1503. --------------------------------------------------------------------------------------
  1504. CREATE FUNCTION [dbo].[pPO_Position] (@changingTimepoint DATETIME2(7))
  1505. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1506. SELECT
  1507.    [PO].PO_ID,
  1508.    [PO_QUA].PO_QUA_Position_Quantity,
  1509.    [PO_QUA].PO_QUA_ChangedAt,
  1510.    [PO_QUA].PO_QUA_RecordedAt,
  1511.    [PO_QUA].PO_QUA_ErasedAt
  1512. FROM
  1513.    [dbo].[PO_Position] [PO]
  1514. LEFT JOIN
  1515.    [dbo].[rcPO_QUA_Position_Quantity] (@changingTimepoint) [PO_QUA]
  1516. ON
  1517.    [PO_QUA].PO_ID = [PO].PO_ID
  1518. AND
  1519.    [PO_QUA].PO_QUA_ChangedAt = (
  1520.       SELECT
  1521.          max(sub.PO_QUA_ChangedAt)
  1522.       FROM
  1523.          [dbo].[rcPO_QUA_Position_Quantity] (@changingTimepoint) sub
  1524.       WHERE
  1525.          sub.PO_ID = [PO].PO_ID
  1526.    );
  1527. GO
  1528.  
  1529. CREATE SYNONYM [dbo].[plPO_Position] FOR [dbo].[pPO_Position];
  1530. GO
  1531.  
  1532. ----------------- [Point-in-changing point-in-recording Perspective] -------------------
  1533. -- PO_Position viewed as was (timepoint) at the given recording timepoint
  1534. --------------------------------------------------------------------------------------
  1535. CREATE FUNCTION [dbo].[ppPO_Position] (@changingTimepoint DATETIME2(7), @recordingTimepoint datetime)
  1536. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1537. SELECT
  1538.    [PO].PO_ID,
  1539.    [PO_QUA].PO_QUA_Position_Quantity,
  1540.    [PO_QUA].PO_QUA_ChangedAt,
  1541.    [PO_QUA].PO_QUA_RecordedAt,
  1542.    [PO_QUA].PO_QUA_ErasedAt
  1543. FROM
  1544.    [dbo].[PO_Position] [PO]
  1545. LEFT JOIN
  1546.    [dbo].[rrPO_QUA_Position_Quantity] (@changingTimepoint, @recordingTimepoint) [PO_QUA]
  1547. ON
  1548.    [PO_QUA].PO_ID = [PO].PO_ID
  1549. AND
  1550.    [PO_QUA].PO_QUA_ChangedAt = (
  1551.       SELECT
  1552.          max(sub.PO_QUA_ChangedAt)
  1553.       FROM
  1554.          [dbo].[rrPO_QUA_Position_Quantity] (@changingTimepoint, @recordingTimepoint) sub
  1555.       WHERE
  1556.          sub.PO_ID = [PO].PO_ID
  1557.    );
  1558. GO
  1559.  
  1560. ------------------------------ [Difference Perspective] ------------------------------
  1561. -- PO_Position viewed by differences in PO_QUA_Position_Quantity
  1562. --------------------------------------------------------------------------------------
  1563. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'dPO_QUA_Position_Quantity' AND type LIKE '%F%')
  1564. DROP FUNCTION [dbo].[dPO_QUA_Position_Quantity];
  1565. GO
  1566. CREATE FUNCTION [dbo].[dPO_QUA_Position_Quantity] (@intervalStart DATETIME2(7), @intervalEnd DATETIME2(7))
  1567. RETURNS TABLE AS RETURN
  1568. SELECT
  1569.    timepoints.inspectedTimepoint,
  1570.    [PO].*
  1571. FROM (
  1572.    SELECT DISTINCT
  1573.       PO_QUA_ChangedAt AS inspectedTimepoint
  1574.    FROM
  1575.       [dbo].[PO_QUA_Position_Quantity]
  1576.    WHERE
  1577.       PO_QUA_ChangedAt BETWEEN @intervalStart AND @intervalEnd
  1578. ) timepoints
  1579. CROSS APPLY
  1580.    pPO_Position(timepoints.inspectedTimepoint) [PO];
  1581. GO
  1582.  
  1583. ------------------------------ [Difference Perspective] ------------------------------
  1584. -- PO_Position viewed by differences in every historized attribute
  1585. --------------------------------------------------------------------------------------
  1586. CREATE FUNCTION [dbo].[dPO_Position] (@intervalStart DATETIME2(7), @intervalEnd DATETIME2(7))
  1587. RETURNS TABLE AS RETURN
  1588. SELECT
  1589.    timepoints.inspectedTimepoint,
  1590.    [PO].*
  1591. FROM (
  1592.    SELECT DISTINCT
  1593.       PO_QUA_ChangedAt AS inspectedTimepoint
  1594.    FROM
  1595.       [dbo].[PO_QUA_Position_Quantity]
  1596.    WHERE
  1597.       PO_QUA_ChangedAt BETWEEN @intervalStart AND @intervalEnd
  1598. ) timepoints
  1599. CROSS APPLY
  1600.    [dbo].[pPO_Position](timepoints.inspectedTimepoint) [PO];
  1601. GO
  1602.  
  1603. ------------------------------------- [Tie Table] ------------------------------------
  1604. -- CU_is_PO_holding table (2-ary)
  1605. --------------------------------------------------------------------------------------
  1606. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'CU_is_PO_holding' and type LIKE '%U%')
  1607. CREATE TABLE [dbo].[CU_is_PO_holding] (
  1608.    CU_ID_is int not null foreign key references [dbo].[CU_Customer](CU_ID),
  1609.    PO_ID_holding int not null foreign key references [dbo].[PO_Position](PO_ID),
  1610.    CU_is_PO_holding_RecordedAt datetime not null,
  1611.    CU_is_PO_holding_ErasedAt datetime not null,
  1612.    constraint uqCU_is_PO_holding unique (
  1613.       CU_is_PO_holding_ErasedAt,
  1614.       PO_ID_holding asc
  1615.    ),
  1616.    constraint pkCU_is_PO_holding primary key (
  1617.       PO_ID_holding asc,
  1618.       CU_is_PO_holding_RecordedAt desc,
  1619.       CU_is_PO_holding_ErasedAt desc
  1620.    )
  1621. ) ON [PRIMARY];
  1622. GO
  1623.  
  1624. -------------------------- [Currently recorded perspective] --------------------------
  1625. -- cCU_is_PO_holding view
  1626. --------------------------------------------------------------------------------------
  1627. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'cCU_is_PO_holding' AND type LIKE '%V%')
  1628. DROP VIEW [dbo].[cCU_is_PO_holding];
  1629. GO
  1630. CREATE VIEW [dbo].[cCU_is_PO_holding] WITH SCHEMABINDING AS
  1631. SELECT
  1632.    tie.CU_ID_is,
  1633.    tie.PO_ID_holding,
  1634.    tie.CU_is_PO_holding_RecordedAt,
  1635.    tie.CU_is_PO_holding_ErasedAt
  1636. FROM
  1637.    [dbo].[CU_is_PO_holding] tie
  1638. WHERE
  1639.    CU_is_PO_holding_ErasedAt >= '9999-12-31';
  1640. GO
  1641.  
  1642. --------------------------- [Rewind recording perspective] ---------------------------
  1643. -- rCU_is_PO_holding function
  1644. --------------------------------------------------------------------------------------
  1645. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'rCU_is_PO_holding' AND type LIKE '%F%')
  1646. DROP FUNCTION [dbo].[rCU_is_PO_holding];
  1647. GO
  1648. CREATE FUNCTION [dbo].[rCU_is_PO_holding] (@recordingTimepoint datetime)
  1649. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1650. SELECT
  1651.    tie.CU_ID_is,
  1652.    tie.PO_ID_holding,
  1653.    tie.CU_is_PO_holding_RecordedAt,
  1654.    tie.CU_is_PO_holding_ErasedAt
  1655. FROM
  1656.    [dbo].[CU_is_PO_holding] tie
  1657. WHERE
  1658.    CU_is_PO_holding_ErasedAt > @recordingTimepoint
  1659. AND
  1660.    CU_is_PO_holding_RecordedAt <= @recordingTimepoint;
  1661. GO
  1662.  
  1663. --------------------------------- [Latest Perspective] -------------------------------
  1664. -- CU_is_PO_holding viewed as is (given by the latest available information)
  1665. --------------------------------------------------------------------------------------
  1666. CREATE VIEW [dbo].[lCU_is_PO_holding] WITH SCHEMABINDING AS
  1667. SELECT
  1668.    tie.CU_ID_is,
  1669.    tie.PO_ID_holding,
  1670.    tie.CU_is_PO_holding_RecordedAt,
  1671.    tie.CU_is_PO_holding_ErasedAt
  1672. FROM
  1673.    [dbo].[cCU_is_PO_holding] tie;
  1674. GO
  1675.  
  1676. CREATE SYNONYM [dbo].[llCU_is_PO_holding] FOR [dbo].[lCU_is_PO_holding];
  1677. GO
  1678.  
  1679. ----------------- [Latest changing point-in-recording Perspective] -------------------
  1680. -- CU_is_PO_holding viewed as is at the given recording timepoint
  1681. --------------------------------------------------------------------------------------
  1682. CREATE FUNCTION [dbo].[lpCU_is_PO_holding] (@recordingTimepoint datetime)
  1683. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1684. SELECT
  1685.    tie.CU_ID_is,
  1686.    tie.PO_ID_holding,
  1687.    tie.CU_is_PO_holding_RecordedAt,
  1688.    tie.CU_is_PO_holding_ErasedAt
  1689. FROM
  1690.    [dbo].[rCU_is_PO_holding](@recordingTimepoint) tie;
  1691. GO
  1692.  
  1693. ---------------------------- [Point-in-Time Perspective] -----------------------------
  1694. -- CU_is_PO_holding viewed as was (at the given timepoint)
  1695. --------------------------------------------------------------------------------------
  1696. CREATE FUNCTION [dbo].[pCU_is_PO_holding] (@changingTimepoint DATETIME2(7))
  1697. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1698. SELECT
  1699.    tie.CU_ID_is,
  1700.    tie.PO_ID_holding,
  1701.    tie.CU_is_PO_holding_RecordedAt,
  1702.    tie.CU_is_PO_holding_ErasedAt
  1703. FROM
  1704.    [dbo].[cCU_is_PO_holding] tie;
  1705. GO
  1706.  
  1707. CREATE SYNONYM [dbo].[plCU_is_PO_holding] FOR [dbo].[pCU_is_PO_holding];
  1708. GO
  1709.  
  1710. ----------------- [Point-in-changing point-in-recording Perspective] -------------------
  1711. -- CU_is_PO_holding viewed as was (timepoint) at the given recording timepoint
  1712. --------------------------------------------------------------------------------------
  1713. CREATE FUNCTION [dbo].[ppCU_is_PO_holding] (@changingTimepoint DATETIME2(7), @recordingTimepoint datetime)
  1714. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1715. SELECT
  1716.    tie.CU_ID_is,
  1717.    tie.PO_ID_holding,
  1718.    tie.CU_is_PO_holding_RecordedAt,
  1719.    tie.CU_is_PO_holding_ErasedAt
  1720. FROM
  1721.    [dbo].[rCU_is_PO_holding](@recordingTimepoint) tie;
  1722. GO
  1723.  
  1724. ------------------------------ [Difference Perspective] ------------------------------
  1725. -- CU_is_PO_holding viewed by differences in the tie
  1726. --------------------------------------------------------------------------------------
  1727. CREATE FUNCTION [dbo].[dCU_is_PO_holding] (@intervalStart DATETIME2(7), @intervalEnd DATETIME2(7))
  1728. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1729. SELECT
  1730.    tie.CU_ID_is,
  1731.    tie.PO_ID_holding,
  1732.    tie.CU_is_PO_holding_RecordedAt,
  1733.    tie.CU_is_PO_holding_ErasedAt
  1734. FROM
  1735.    [dbo].[cCU_is_PO_holding] tie;
  1736. GO
  1737.  
  1738. ------------------------------------- [Tie Table] ------------------------------------
  1739. -- PO_for_CO_the table (2-ary)
  1740. --------------------------------------------------------------------------------------
  1741. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'PO_for_CO_the' and type LIKE '%U%')
  1742. CREATE TABLE [dbo].[PO_for_CO_the] (
  1743.    PO_ID_for int not null foreign key references [dbo].[PO_Position](PO_ID),
  1744.    CO_ID_the int not null foreign key references [dbo].[CO_Company](CO_ID),
  1745.    PO_for_CO_the_RecordedAt datetime not null,
  1746.    PO_for_CO_the_ErasedAt datetime not null,
  1747.    constraint uqPO_for_CO_the unique (
  1748.       PO_for_CO_the_ErasedAt,
  1749.       PO_ID_for asc
  1750.    ),
  1751.    constraint pkPO_for_CO_the primary key (
  1752.       PO_ID_for asc,
  1753.       PO_for_CO_the_RecordedAt desc,
  1754.       PO_for_CO_the_ErasedAt desc
  1755.    )
  1756. ) ON [PRIMARY];
  1757. GO
  1758.  
  1759. -------------------------- [Currently recorded perspective] --------------------------
  1760. -- cPO_for_CO_the view
  1761. --------------------------------------------------------------------------------------
  1762. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'cPO_for_CO_the' AND type LIKE '%V%')
  1763. DROP VIEW [dbo].[cPO_for_CO_the];
  1764. GO
  1765. CREATE VIEW [dbo].[cPO_for_CO_the] WITH SCHEMABINDING AS
  1766. SELECT
  1767.    tie.PO_ID_for,
  1768.    tie.CO_ID_the,
  1769.    tie.PO_for_CO_the_RecordedAt,
  1770.    tie.PO_for_CO_the_ErasedAt
  1771. FROM
  1772.    [dbo].[PO_for_CO_the] tie
  1773. WHERE
  1774.    PO_for_CO_the_ErasedAt >= '9999-12-31';
  1775. GO
  1776.  
  1777. --------------------------- [Rewind recording perspective] ---------------------------
  1778. -- rPO_for_CO_the function
  1779. --------------------------------------------------------------------------------------
  1780. IF EXISTS (SELECT * FROM sys.objects WHERE name = 'rPO_for_CO_the' AND type LIKE '%F%')
  1781. DROP FUNCTION [dbo].[rPO_for_CO_the];
  1782. GO
  1783. CREATE FUNCTION [dbo].[rPO_for_CO_the] (@recordingTimepoint datetime)
  1784. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1785. SELECT
  1786.    tie.PO_ID_for,
  1787.    tie.CO_ID_the,
  1788.    tie.PO_for_CO_the_RecordedAt,
  1789.    tie.PO_for_CO_the_ErasedAt
  1790. FROM
  1791.    [dbo].[PO_for_CO_the] tie
  1792. WHERE
  1793.    PO_for_CO_the_ErasedAt > @recordingTimepoint
  1794. AND
  1795.    PO_for_CO_the_RecordedAt <= @recordingTimepoint;
  1796. GO
  1797.  
  1798. --------------------------------- [Latest Perspective] -------------------------------
  1799. -- PO_for_CO_the viewed as is (given by the latest available information)
  1800. --------------------------------------------------------------------------------------
  1801. CREATE VIEW [dbo].[lPO_for_CO_the] WITH SCHEMABINDING AS
  1802. SELECT
  1803.    tie.PO_ID_for,
  1804.    tie.CO_ID_the,
  1805.    tie.PO_for_CO_the_RecordedAt,
  1806.    tie.PO_for_CO_the_ErasedAt
  1807. FROM
  1808.    [dbo].[cPO_for_CO_the] tie;
  1809. GO
  1810.  
  1811. CREATE SYNONYM [dbo].[llPO_for_CO_the] FOR [dbo].[lPO_for_CO_the];
  1812. GO
  1813.  
  1814. ----------------- [Latest changing point-in-recording Perspective] -------------------
  1815. -- PO_for_CO_the viewed as is at the given recording timepoint
  1816. --------------------------------------------------------------------------------------
  1817. CREATE FUNCTION [dbo].[lpPO_for_CO_the] (@recordingTimepoint datetime)
  1818. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1819. SELECT
  1820.    tie.PO_ID_for,
  1821.    tie.CO_ID_the,
  1822.    tie.PO_for_CO_the_RecordedAt,
  1823.    tie.PO_for_CO_the_ErasedAt
  1824. FROM
  1825.    [dbo].[rPO_for_CO_the](@recordingTimepoint) tie;
  1826. GO
  1827.  
  1828. ---------------------------- [Point-in-Time Perspective] -----------------------------
  1829. -- PO_for_CO_the viewed as was (at the given timepoint)
  1830. --------------------------------------------------------------------------------------
  1831. CREATE FUNCTION [dbo].[pPO_for_CO_the] (@changingTimepoint DATETIME2(7))
  1832. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1833. SELECT
  1834.    tie.PO_ID_for,
  1835.    tie.CO_ID_the,
  1836.    tie.PO_for_CO_the_RecordedAt,
  1837.    tie.PO_for_CO_the_ErasedAt
  1838. FROM
  1839.    [dbo].[cPO_for_CO_the] tie;
  1840. GO
  1841.  
  1842. CREATE SYNONYM [dbo].[plPO_for_CO_the] FOR [dbo].[pPO_for_CO_the];
  1843. GO
  1844.  
  1845. ----------------- [Point-in-changing point-in-recording Perspective] -------------------
  1846. -- PO_for_CO_the viewed as was (timepoint) at the given recording timepoint
  1847. --------------------------------------------------------------------------------------
  1848. CREATE FUNCTION [dbo].[ppPO_for_CO_the] (@changingTimepoint DATETIME2(7), @recordingTimepoint datetime)
  1849. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1850. SELECT
  1851.    tie.PO_ID_for,
  1852.    tie.CO_ID_the,
  1853.    tie.PO_for_CO_the_RecordedAt,
  1854.    tie.PO_for_CO_the_ErasedAt
  1855. FROM
  1856.    [dbo].[rPO_for_CO_the](@recordingTimepoint) tie;
  1857. GO
  1858.  
  1859. ------------------------------ [Difference Perspective] ------------------------------
  1860. -- PO_for_CO_the viewed by differences in the tie
  1861. --------------------------------------------------------------------------------------
  1862. CREATE FUNCTION [dbo].[dPO_for_CO_the] (@intervalStart DATETIME2(7), @intervalEnd DATETIME2(7))
  1863. RETURNS TABLE WITH SCHEMABINDING AS RETURN
  1864. SELECT
  1865.    tie.PO_ID_for,
  1866.    tie.CO_ID_the,
  1867.    tie.PO_for_CO_the_RecordedAt,
  1868.    tie.PO_for_CO_the_ErasedAt
  1869. FROM
  1870.    [dbo].[cPO_for_CO_the] tie;
  1871. GO
  1872.  
  1873. --------------------------------- [Schema Evolution] ---------------------------------
  1874. -- Schema evolution tables, views and functions
  1875. --------------------------------------------------------------------------------------
  1876. IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = '_Schema' and type LIKE '%U%')
  1877.    CREATE TABLE [_Schema] (
  1878.       [version] int identity(1, 1) not null primary key,
  1879.       [activation] DATETIME2(7) not null,
  1880.       [schema] xml not null
  1881.    );
  1882. GO
  1883.  
  1884. INSERT INTO [_Schema] (
  1885.    [activation],
  1886.    [schema]
  1887. )
  1888. SELECT
  1889.    current_timestamp,
  1890.    N'<schema><metadata format="0.94" temporalization="bi"/><knot mnemonic="TIC" descriptor="Ticker" identity="smallint" dataRange="varchar(6)"><metadata capsule="dbo" generator="false"/><layout x="829.78" y="32.45" fixed="false"/></knot><knot mnemonic="RAT" descriptor="Rating" identity="tinyint" dataRange="char(1)"><metadata capsule="dbo" generator="false"/><layout x="464.58" y="368.24" fixed="false"/></knot><anchor mnemonic="CO" descriptor="Company" identity="int"><metadata capsule="dbo" generator="true"/><attribute mnemonic="TIC" descriptor="Ticker" knotRange="TIC"><metadata capsule="dbo"/><layout x="800.42" y="78.62" fixed="false"/></attribute><layout x="777.21" y="152.28" fixed="false"/></anchor><anchor mnemonic="CU" descriptor="Customer" identity="int"><metadata capsule="dbo" generator="true"/><attribute mnemonic="RAT" descriptor="Rating" timeRange="datetime" knotRange="RAT"><metadata capsule="dbo"/><layout x="520.76" y="403.15" fixed="false"/></attribute><attribute mnemonic="NAM" descriptor="Name" dataRange="varchar(42)"><metadata capsule="dbo"/><layout x="623.23" y="476.92" fixed="false"/></attribute><layout x="601.62" y="413.27" fixed="false"/></anchor><anchor mnemonic="PO" descriptor="Position" identity="int"><metadata capsule="dbo" generator="true"/><attribute mnemonic="QUA" descriptor="Quantity" timeRange="datetime" dataRange="int"><metadata capsule="dbo"/><layout x="609.43" y="229.66" fixed="false"/></attribute><layout x="672.26" y="267.43" fixed="false"/></anchor><tie><anchorRole role="is" type="CU" identifier="false"/><anchorRole role="holding" type="PO" identifier="true"/><metadata capsule="dbo"/><layout x="647.30" y="349.69" fixed="false"/></tie><tie><anchorRole role="for" type="PO" identifier="true"/><anchorRole role="the" type="CO" identifier="false"/><metadata capsule="dbo"/><layout x="731.35" y="220.87" fixed="false"/></tie></schema>';
  1891. GO
  1892.  
  1893. IF EXISTS (SELECT * FROM sys.views WHERE name = '_Anchor')
  1894. DROP VIEW [_Anchor]
  1895. GO
  1896.  
  1897. CREATE VIEW [_Anchor]
  1898. AS
  1899. SELECT
  1900.    S.version,
  1901.    S.activation,
  1902.    Nodeset.anchor.value('concat(@mnemonic, "_", @descriptor)', 'nvarchar(max)') as [name],
  1903.    Nodeset.anchor.value('metadata[1]/@capsule', 'nvarchar(max)') as [capsule],
  1904.    Nodeset.anchor.value('@mnemonic', 'nvarchar(max)') as [mnemonic],
  1905.    Nodeset.anchor.value('@descriptor', 'nvarchar(max)') as [descriptor],
  1906.    Nodeset.anchor.value('@identity', 'nvarchar(max)') as [identity],
  1907.    Nodeset.anchor.value('metadata[1]/@generator', 'nvarchar(max)') as [generator],
  1908.    Nodeset.anchor.value('count(attribute)', 'int') as [numberOfAttributes]
  1909. FROM
  1910.    [_Schema] S
  1911. CROSS APPLY
  1912.    S.[schema].nodes('/schema/anchor') as Nodeset(anchor);
  1913. GO
  1914.  
  1915. IF EXISTS (SELECT * FROM sys.views WHERE name = '_Knot')
  1916. DROP VIEW [_Knot]
  1917. GO
  1918.  
  1919. CREATE VIEW [_Knot]
  1920. AS
  1921. SELECT
  1922.    S.version,
  1923.    S.activation,
  1924.    Nodeset.knot.value('concat(@mnemonic, "_", @descriptor)', 'nvarchar(max)') as [name],
  1925.    Nodeset.knot.value('metadata[1]/@capsule', 'nvarchar(max)') as [capsule],
  1926.    Nodeset.knot.value('@mnemonic', 'nvarchar(max)') as [mnemonic],
  1927.    Nodeset.knot.value('@descriptor', 'nvarchar(max)') as [descriptor],
  1928.    Nodeset.knot.value('@identity', 'nvarchar(max)') as [identity],
  1929.    Nodeset.knot.value('metadata[1]/@generator', 'nvarchar(max)') as [generator],
  1930.    Nodeset.knot.value('@dataRange', 'nvarchar(max)') as [dataRange]
  1931. FROM
  1932.    [_Schema] S
  1933. CROSS APPLY
  1934.    S.[schema].nodes('/schema/knot') as Nodeset(knot);
  1935. GO
  1936.  
  1937. IF EXISTS (SELECT * FROM sys.views WHERE name = '_Attribute')
  1938. DROP VIEW [_Attribute]
  1939. GO
  1940.  
  1941. CREATE VIEW [_Attribute]
  1942. AS
  1943. SELECT
  1944.    S.version,
  1945.    S.activation,
  1946.    ParentNodeset.anchor.value('concat(@mnemonic, "_")', 'nvarchar(max)') +
  1947.    Nodeset.attribute.value('concat(@mnemonic, "_")', 'nvarchar(max)') +
  1948.    ParentNodeset.anchor.value('concat(@descriptor, "_")', 'nvarchar(max)') +
  1949.    Nodeset.attribute.value('@descriptor', 'nvarchar(max)') as [name],
  1950.    Nodeset.attribute.value('metadata[1]/@capsule', 'nvarchar(max)') as [capsule],
  1951.    Nodeset.attribute.value('@mnemonic', 'nvarchar(max)') as [mnemonic],
  1952.    Nodeset.attribute.value('@descriptor', 'nvarchar(max)') as [descriptor],
  1953.    ParentNodeset.anchor.value('@mnemonic', 'nvarchar(max)') as [anchorMnemonic],
  1954.    ParentNodeset.anchor.value('@descriptor', 'nvarchar(max)') as [anchorDescriptor],
  1955.    ParentNodeset.anchor.value('@identity', 'nvarchar(max)') as [anchorIdentity],
  1956.    Nodeset.attribute.value('@dataRange', 'nvarchar(max)') as [dataRange],
  1957.    Nodeset.attribute.value('@knotRange', 'nvarchar(max)') as [knotRange],
  1958.    Nodeset.attribute.value('@timeRange', 'nvarchar(max)') as [timeRange]
  1959. FROM
  1960.    [_Schema] S
  1961. CROSS APPLY
  1962.    S.[schema].nodes('/schema/anchor') as ParentNodeset(anchor)
  1963. OUTER APPLY
  1964.    ParentNodeset.anchor.nodes('attribute') as Nodeset(attribute);
  1965. GO
  1966.  
  1967. IF EXISTS (SELECT * FROM sys.views WHERE name = '_Tie')
  1968. DROP VIEW [_Tie]
  1969. GO
  1970.  
  1971. CREATE VIEW [_Tie]
  1972. AS
  1973. SELECT
  1974.    S.version,
  1975.    S.activation,
  1976.    REPLACE(Nodeset.tie.query('
  1977.      for $role in *[local-name() = "anchorRole" or local-name() = "knotRole"]
  1978.      return concat($role/@type, "_", $role/@role)
  1979.   ').value('.', 'nvarchar(max)'), ' ', '_') as [name],
  1980.    Nodeset.tie.value('metadata[1]/@capsule', 'nvarchar(max)') as [capsule],
  1981.    Nodeset.tie.value('count(anchorRole) + count(knotRole)', 'int') as [numberOfRoles],
  1982.    Nodeset.tie.query('
  1983.      for $role in *[local-name() = "anchorRole" or local-name() = "knotRole"]
  1984.      return string($role/@role)
  1985.   ').value('.', 'nvarchar(max)') as [roles],
  1986.    Nodeset.tie.value('count(anchorRole)', 'int') as [numberOfAnchors],
  1987.    Nodeset.tie.query('
  1988.      for $role in anchorRole
  1989.      return string($role/@type)
  1990.   ').value('.', 'nvarchar(max)') as [anchors],
  1991.    Nodeset.tie.value('count(knotRole)', 'int') as [numberOfKnots],
  1992.    Nodeset.tie.query('
  1993.      for $role in knotRole
  1994.      return string($role/@type)
  1995.   ').value('.', 'nvarchar(max)') as [knots],
  1996.    Nodeset.tie.value('count(*[local-name() = "anchorRole" or local-name() = "knotRole"][@identifier = "true"])', 'int') as [numberOfIdentifiers],
  1997.    Nodeset.tie.query('
  1998.      for $role in *[local-name() = "anchorRole" or local-name() = "knotRole"][@identifier = "true"]
  1999.      return string($role/@type)
  2000.   ').value('.', 'nvarchar(max)') as [identifiers],
  2001.    Nodeset.tie.value('@timeRange', 'nvarchar(max)') as [timeRange]
  2002. FROM
  2003.    [_Schema] S
  2004. CROSS APPLY
  2005.    S.[schema].nodes('/schema/tie') as Nodeset(tie);
  2006. GO
  2007.  
  2008. IF EXISTS (SELECT * FROM sys.objects WHERE name = '_Evolution' and type LIKE '%F%')
  2009. DROP FUNCTION [_Evolution];
  2010. GO
  2011.  
  2012. CREATE FUNCTION _Evolution (
  2013.       @timepoint AS DATETIME2(7)
  2014. )
  2015. RETURNS TABLE
  2016. RETURN
  2017. SELECT
  2018.    V.[version],
  2019.    ISNULL(S.[name], T.[name]) AS [name],
  2020.    ISNULL(V.[activation], T.[create_date]) AS [activation],
  2021.    CASE
  2022.       WHEN S.[name] is null THEN
  2023.          CASE
  2024.             WHEN T.[create_date] > (
  2025.                SELECT
  2026.                   ISNULL(MAX([activation]), @timepoint)
  2027.                FROM
  2028.                   [_Schema]
  2029.                WHERE
  2030.                   [activation] <= @timepoint
  2031.             ) THEN 'Future'
  2032.             ELSE 'Past'
  2033.          END
  2034.       WHEN T.[name] is null THEN 'Missing'
  2035.       ELSE 'Present'
  2036.    END AS Existence
  2037. FROM (
  2038.    SELECT
  2039.       MAX([version]) as [version],
  2040.       MAX([activation]) as [activation]
  2041.    FROM
  2042.       [_Schema]
  2043.    WHERE
  2044.       [activation] <= @timepoint
  2045. ) V
  2046. JOIN (
  2047.    SELECT
  2048.       [name],
  2049.       [version]
  2050.    FROM
  2051.       [_Anchor] a
  2052.    UNION ALL
  2053.    SELECT
  2054.       [name],
  2055.       [version]
  2056.    FROM
  2057.       [_Knot] k
  2058.    UNION ALL
  2059.    SELECT
  2060.       [name],
  2061.       [version]
  2062.    FROM
  2063.       [_Attribute] b
  2064.    UNION ALL
  2065.    SELECT
  2066.       [name],
  2067.       [version]
  2068.    FROM
  2069.       [_Tie] t
  2070. ) S
  2071. ON
  2072.    S.[version] = V.[version]
  2073. FULL OUTER JOIN (
  2074.    SELECT
  2075.       [name],
  2076.       [create_date]
  2077.    FROM
  2078.       sys.tables
  2079.    WHERE
  2080.       [type] like '%U%'
  2081.    AND
  2082.       LEFT([name], 1) <> '_'
  2083. ) T
  2084. ON
  2085.       S.[name] = T.[name]
  2086. GO
  2087.  
  2088.  
  2089. ------------------------------------ LOAD DATA ---------------------------------------
  2090.  
  2091. insert into TIC_Ticker (
  2092.     TIC_ID,
  2093.     TIC_Ticker
  2094. ) values
  2095. (1, 'XOM');
  2096.  
  2097. insert into lCO_Company (
  2098.     TIC_Ticker,
  2099.     CO_TIC_RecordedAt,
  2100.     CO_TIC_ErasedAt
  2101. ) values
  2102. ('XOM', '2011-02-01', '9999-12-31');
  2103.    
  2104. insert into RAT_Rating (
  2105.     RAT_ID,
  2106.     RAT_Rating
  2107. ) values
  2108. (1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E');
  2109.  
  2110. insert into lCU_Customer (
  2111.     CU_NAM_Customer_Name,
  2112.     CU_NAM_RecordedAt,
  2113.     CU_NAM_ErasedAt
  2114. ) values
  2115. ('Bridgewater Associates', '2011-01-01', '9999-12-31');
  2116.    
  2117. insert into lCU_Customer (
  2118.     CU_ID,
  2119.     RAT_Rating,
  2120.     CU_RAT_ChangedAt,
  2121.     CU_RAT_RecordedAt,
  2122.     CU_RAT_ErasedAt
  2123. ) values
  2124. (1, 'D', '2011-03-20', '2011-03-21', '9999-12-31'),
  2125. (1, 'E', '2011-03-18', '2011-03-21', '9999-12-31'),
  2126. (1, 'A', '2011-03-18', '2011-03-18', '2011-03-19'),
  2127. (1, 'D', '2011-03-17', '2011-03-21', '9999-12-31'),
  2128. (1, 'D', '2011-03-17', '2011-03-20', '2011-03-21'),
  2129. (1, 'A', '2011-03-17', '2011-03-17', '2011-03-18'),
  2130. (1, 'B', '2011-03-16', '2011-03-18', '2011-03-19'),
  2131. (1, 'C', '2011-03-15', '2011-03-20', '9999-12-31'),
  2132. (1, 'C', '2011-03-15', '2011-03-19', '2011-03-20');
  2133.  
  2134. -- This SP creates the given number of identities.
  2135. exec kPO_Position 1;
  2136.  
  2137. insert into lPO_Position (
  2138.     PO_ID,
  2139.     PO_QUA_Position_Quantity,
  2140.     PO_QUA_ChangedAt,
  2141.     PO_QUA_RecordedAt,
  2142.     PO_QUA_ErasedAt
  2143. ) values
  2144. (1, 1,      '2011-03-17', '2011-03-17', '2011-03-18'),
  2145. (1, 20,     '2011-03-16', '2011-03-18', '2011-03-19'),
  2146. (1, 300,    '2011-03-15', '2011-03-19', '2011-03-20'),
  2147. (1, 4000,   '2011-03-17', '2011-03-20', '2011-03-21'),
  2148. (1, 50000'2011-03-18', '2011-03-21', '9999-12-31'),
  2149. (1, 300,    '2011-03-15', '2011-03-20', '9999-12-31'),
  2150. (1, 4000,   '2011-03-17', '2011-03-21', '9999-12-31');
  2151.  
  2152. insert into CU_is_PO_holding (
  2153.     CU_ID_is,
  2154.     PO_ID_holding,
  2155.     CU_is_PO_holding_RecordedAt,
  2156.     CU_is_PO_holding_ErasedAt
  2157. ) values
  2158. (1, 1, '2011-03-15', '9999-12-31');
  2159.  
  2160. insert into PO_for_CO_the (
  2161.     PO_ID_for,
  2162.     CO_ID_the,
  2163.     PO_for_CO_the_RecordedAt,
  2164.     PO_for_CO_the_ErasedAt
  2165. ) values
  2166. (1, 1, '2011-03-15', '9999-12-31');
  2167.  
  2168. ----------------------------------- QUERY DATA ---------------------------------------
  2169. -- using latest changing latest recording
  2170. --------------------------------------------------------------------------------------
  2171. select
  2172.     cu.CU_NAM_Customer_Name,
  2173.     cu.RAT_Rating,
  2174.     po.PO_QUA_Position_Quantity,
  2175.     co.TIC_Ticker
  2176. from
  2177.     llCU_Customer cu
  2178. join
  2179.     llCU_is_PO_holding cupo
  2180. on
  2181.     cupo.CU_ID_is = cu.CU_ID
  2182. join
  2183.     llPO_Position po
  2184. on
  2185.     po.PO_ID = cupo.PO_ID_holding
  2186. join
  2187.     llPO_for_CO_the poco
  2188. on
  2189.     poco.PO_ID_for = po.PO_ID
  2190. join
  2191.     llCO_Company co
  2192. on
  2193.     co.CO_ID = poco.CO_ID_the;
  2194.    
  2195. --------------------------------------------------------------------------------------
  2196. -- using point in changing point in recording
  2197. --------------------------------------------------------------------------------------
  2198. select
  2199.     cu.CU_NAM_Customer_Name,
  2200.     cu.RAT_Rating,
  2201.     po.PO_QUA_Position_Quantity,
  2202.     co.TIC_Ticker
  2203. from
  2204.     ppCU_Customer('2011-03-16', '2011-03-19') cu
  2205. join
  2206.     llCU_is_PO_holding cupo
  2207. on
  2208.     cupo.CU_ID_is = cu.CU_ID
  2209. join
  2210.     ppPO_Position('2011-03-16', '2011-03-19') po
  2211. on
  2212.     po.PO_ID = cupo.PO_ID_holding
  2213. join
  2214.     llPO_for_CO_the poco
  2215. on
  2216.     poco.PO_ID_for = po.PO_ID
  2217. join
  2218.     llCO_Company co
  2219. on
  2220.     co.CO_ID = poco.CO_ID_the;
  2221.  
  2222. --------------------------------------------------------------------------------------
  2223. -- a pattern for a temporally dependent join (the above are independent)
  2224. --------------------------------------------------------------------------------------
  2225. select
  2226.     cu.CU_NAM_Customer_Name,
  2227.     cu.RAT_Rating,
  2228.     po.PO_QUA_Position_Quantity,
  2229.     po.PO_QUA_ChangedAt,
  2230.     co.TIC_Ticker
  2231. from
  2232.     ppCU_Customer('2011-03-16', '2011-03-19') cu
  2233. join
  2234.     llCU_is_PO_holding cupo
  2235. on
  2236.     cupo.CU_ID_is = cu.CU_ID
  2237. cross apply
  2238.     ppPO_Position((
  2239.         select
  2240.             min(PO_QUA_ChangedAt)
  2241.         from
  2242.             PO_QUA_Position_Quantity PO_QUA
  2243.         where
  2244.             PO_QUA.PO_ID = cupo.PO_ID_holding
  2245.         ),
  2246.         '9999-12-30'
  2247.     ) po
  2248. join
  2249.     llPO_for_CO_the poco
  2250. on
  2251.     poco.PO_ID_for = po.PO_ID
  2252. join
  2253.     llCO_Company co
  2254. on
  2255.     co.CO_ID = poco.CO_ID_the
  2256. where
  2257.     po.PO_ID = cupo.PO_ID_holding;
  2258.  
  2259. --------------------------------------------------------------------------------------
  2260. -- This model will also handle a situation where for
  2261. -- example a position was wrongfully associated with
  2262. -- a company or customer, in which situation you can
  2263. -- use the pp-views on the ties to "time-travel".
  2264. --------------------------------------------------------------------------------------