IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = N'TransformProvanceBFATitleLicensingPositionDailyFactProc')
BEGIN
EXECUTE ('CREATE PROCEDURE dbo.[TransformProvanceBFATitleLicensingPositionDailyFactProc] @WaterMark xml AS RETURN 1')
END
GO
ALTER PROCEDURE [dbo].[TransformProvanceBFATitleLicensingPositionDailyFactProc] (@WaterMark xml)
AS
BEGIN
SET NOCOUNT ON
SET XACT_ABORT ON
In ServiceManager the logical key for BFATitleLicensingPosition is SoftwareTitleGuid, our prefered logical key in the DW would be SoftwareTitleGuid and StartDay
The "system" will add ProvanceBFATitleLicensingPositionDimKey and DateKey to the Fact and to the Primary Key, these should never be updated.
The BFA process can be run many times during a day, we want the last run of each day to be saved.
The BFA process may not run every day, or a title may not change every day, the DailyFact will have a StartDay and EndDay field, these represent the days this record was in effect.
The extract process may run many times before the transform process, this could give us many records for a given logical key, we keep the last record for each day, the EndDay of each will be the StartDay -1
of the next record.
The Timestamp field on the inbound.MTV_Provance$Class$BFATitleLicensingPosition must always move forward. If it is set to a date previous to its current value this procedure could fail
or produce inconsitant results.
insert into t_log (t_xml,t_date) values (@WaterMark,getdate())
begin transaction
insert into t_log (t_xml,t_date) values (null,getdate())
rollback
create table T_log (t_id int not null identity,t_xml xml,t_date datetime)
SELECT @task = 'Shreding WaterMark.'
SELECT * INTO #wm FROM etl.ShredWaterMark(@WaterMark)
SELECT @task = 'Getting Water Mark Date and BatchId.'
SELECT TOP 1 @WaterMarkDate = WaterMark, @BatchId = BatchId
FROM #wm
WHERE WarehouseEntityName = N'MTV_Provance$Class$BFA$TitleLicensingPosition'
SET @CurrentUtcDate = GETUTCDATE()
-- Get the inbound data
-- Join to ProvanceBFATitleLicensingPositionDimvw to get the ProvanceBFATitleLicensingPositionDimKey
SELECT @task = 'Moving inbound data to #Temp1'
select CAST(CONVERT(nvarchar(8), a.TimeStamp, 112) AS INT) AS StartDay,
CAST(NULL AS int) AS EndDay,
ROW_NUMBER() OVER (PARTITION BY a.SoftwareTitleGuid
ORDER BY a.TimeStamp ) AS KeySeqNum,
CAST(CONVERT(nvarchar(8), a.TimeAdded, 112) AS INT) AS DateKey,
A.*
into #Temp1
from ( SELECT INB.[Provance.Class.BFA.TitleLicensingPosition!AssignmentCount] AS AssignmentCount,
INB.BaseManagedEntityId AS BaseManagedEntityId,
INB.[Provance.Class.BFA.TitleLicensingPosition!BatchId] AS BatchId,
INB.[System.Entity!DisplayName] AS DisplayName,
INB.[Provance.Class.BFA.TitleLicensingPosition!EntitlementsAvailable] AS EntitlementsAvailable,
INB.[Provance.Class.BFA.TitleLicensingPosition!EntitlementsRemaining] AS EntitlementsRemaining,
INB.[Provance.Class.BFA.TitleLicensingPosition!InstallsCovered] AS InstallsCovered,
INB.[Provance.Class.BFA.TitleLicensingPosition!InstallsExcluded] AS InstallsExcluded,
INB.[Provance.Class.BFA.TitleLicensingPosition!InstallsNormalized] AS InstallsNormalized,
INB.[Provance.Class.BFA.TitleLicensingPosition!InstallsNotCovered] AS InstallsNotCovered,
INB.[Provance.Class.BFA.TitleLicensingPosition!LicensingPositionIndicatorId] AS LicensingPositionIndicatorId,
INB.[Provance.Class.BFA.TitleLicensingPosition!LicensingPositionPercentage] AS LicensingPositionPercentage,
Dim.ProvanceBFATitleLicensingPositionDimKey AS ProvanceBFATitleLicensingPositionDimKey,
INB.[Provance.Class.BFA.TitleLicensingPosition!SoftwareTitleGuid] AS SoftwareTitleGuid,
INB.[Provance.Class.BFA.TitleLicensingPosition!TimeStamp] AS TimeStamp,
INB.[Provance.Class.BFA.TitleLicensingPosition!TitleLicensingPositionId] AS TitleLicensingPositionId,
ROW_NUMBER() OVER (PARTITION BY [Provance.Class.BFA.TitleLicensingPosition!SoftwareTitleGuid], CAST(CONVERT(nvarchar(8), INB.[Provance.Class.BFA.TitleLicensingPosition!TimeStamp], 112) AS INT)
ORDER BY INB.[Provance.Class.BFA.TitleLicensingPosition!TimeStamp] DESC,
INB.[Provance.Class.BFA.TitleLicensingPosition!BatchId] DESC)
AS DaySeqNum,
INB.TimeAdded AS TimeAdded
FROM inbound.MTV_Provance$Class$BFA$TitleLicensingPosition INB
LEFT JOIN dbo.ProvanceBFATitleLicensingPositionDimvw Dim ON Dim.BaseManagedEntityId = INB.BaseManagedEntityId
WHERE INB.DWTimestamp >= @WaterMarkDate
AND INB.DWTimestamp < @CurrentUtcDate) A
where a.DaySeqNum = 1 -- Keep the most recent record by day
-- If there are any early arrivals - e.g. no row in ProvanceBFATitleLicensingPositionDimvw yet, update their DWTimestamp so we get them
-- on the next run
SELECT @task = 'Rejecting early arriving records'
UPDATE INB
SET DWTimestamp = @CurrentUtcDate
FROM inbound.MTV_Provance$Class$BFA$TitleLicensingPosition INB
JOIN #Temp1 T ON INB.BaseManagedEntityId = T.BaseManagedEntityId
WHERE T.ProvanceBFATitleLicensingPositionDimKey IS NULL
AND INB.DWTimestamp >= @WaterMarkDate
AND INB.DWTimestamp < @CurrentUtcDate
DELETE FROM #Temp1 WHERE ProvanceBFATitleLicensingPositionDimKey IS NULL
-- KeySeqNo will put records in order of SoftwareTitleGuid,Timestamp each record will be assigned an EndDay that is one day before the StartDay
-- of the next record in order.
SELECT @task = 'Setting EndDay for new facts in t#Temp1'
UPDATE T1
SET T1.EndDay = CAST(CONVERT(nvarchar(8), DATEADD(D,-1,T2.TimeStamp), 112) AS INT)
FROM #Temp1 T1
JOIN #Temp1 T2 ON T1.SoftwareTitleGuid = T2.SoftwareTitleGuid
AND T1.KeySeqNum + 1 = T2.KeySeqNum
-- The should only be one row per SoftwareTitleGuid that has a null EndDay in BFATitleLicensingPositionDailyFactvw
-- The oldest per SoftwareTitleGuid in #Temp table (T.KeySeqNo = 1) will be used to set the EndDay of that record
-- if it is older than the oldest in the temp table.
SELECT @task = 'Setting EndDay for exising facts'
UPDATE F
SET F.EndDay = CAST(CONVERT(nvarchar(8), DATEADD(D,-1,T.TimeStamp), 112) AS INT),
UpdatedBatchId = @BatchId
FROM dbo.ProvanceBFATitleLicensingPositionDailyFactvw F
JOIN #Temp1 T ON F.SoftwareTitleGuid = T.SoftwareTitleGuid
AND F.StartDay < T.StartDay
AND T.KeySeqNum = 1
WHERE F.EndDay is Null
SELECT @Updated = @Updated + @@rowcount
-- Remove the rows that already exist
DELETE T
FROM #Temp1 T
JOIN dbo.ProvanceBFATitleLicensingPositionDailyFactvw F ON T.SoftwareTitleGuid = F.SoftwareTitleGuid
AND T.StartDay = F.StartDay
-- Insert new facts
SELECT @task = 'Insert new facts.'
INSERT INTO dbo.ProvanceBFATitleLicensingPositionDailyFactvw (
AssignmentCount,
BatchId,
DateKey,
DisplayName,
EndDay,
EntitlementsAvailable,
EntitlementsRemaining,
InsertedBatchId,
InstallsCovered,
InstallsExcluded,
InstallsNormalized,
InstallsNotCovered,
LicensingPositionIndicatorId,
LicensingPositionPercentage,
ProvanceBFATitleLicensingPositionDimKey,
SoftwareTitleGuid,
StartDay,
TimeStamp,
TitleLicensingPositionId,
UpdatedBatchId)
SELECT
T.AssignmentCount,
T.BatchId,
T.DateKey,
t.DisplayName,
T.EndDay,
T.EntitlementsAvailable,
T.EntitlementsRemaining,
@BatchId,
T.InstallsCovered,
T.InstallsExcluded,
T.InstallsNormalized,
T.InstallsNotCovered,
T.LicensingPositionIndicatorId,
T.LicensingPositionPercentage,
T.ProvanceBFATitleLicensingPositionDimKey,
T.SoftwareTitleGuid,
T.StartDay,
T.TimeStamp,
T.TitleLicensingPositionId,
@BatchId
FROM #Temp1 T
SELECT @Inserted = @@rowcount
-- Test code...
--select 1 stepc, getdate() datec,* into temp_wm from #wm a
--insert into temp_wm select 1 stepc, getdate() datec,* from #wm a
-- select * from temp_wm order by datec,stepc
-- sp_help temp_wm
SELECT @task = 'Updating Watermark.'
UPDATE #wm SET WaterMark = CONVERT(nvarchar(64), isnull(@CurrentUtcDate, '1/1/1900'), 109)
WHERE WarehouseEntityName = N'MTV_Provance$Class$BFA$TitleLicensingPosition' and WaterMarkType= N'DateTime'
SELECT @WaterMark = (SELECT ModuleName AS "@ModuleName",
ProcessName AS "@ProcessName",
@BatchId AS "@BatchId",
(SELECT DISTINCT
WarehouseEntityName AS "@WarehouseEntityName",
WarehouseEntityTypeName AS "@WarehouseEntityTypeName",
EntityGuid AS "@EntityGuid",
CASE WarehouseEntityTypeName
WHEN 'Inbound' THEN 'DateTime'
ELSE 'BatchId' END AS "@WaterMarkType",
WaterMark AS "@WaterMark"
FROM #wm
FOR XML path('Entity'), type)
FROM (SELECT DISTINCT ModuleName, ProcessName from #wm) a
FOR XML path('Module'), type)
SELECT @WaterMark as WaterMark, @BatchId as BatchId, @Updated as UpdatedRowCount, @Inserted as InsertedRowCount
END TRY
BEGIN CATCH
DECLARE @errorFmt VARCHAR(256)