在 Azure 突触分析中创建日期维度

Create date dimension in Azure synapse analytics

我使用 2 个存储过程在 Synapse 中创建一个 date_dimension。第一个 proc 创建年份的详细信息,第二个 proc 迭代它以通过副本创建年份范围 activity.

第二个过程有 2 个导入参数,即 YearStart=2000 和 YearEnd=2030。但是,当我执行副本 activity 时,它只会创建日期 table only for one year (2000) 并且它循环似乎不起作用!

这是第二个过程。

CREATE OR ALTER PROCEDURE [PopulateDateDimensionForYearRange] @YearStart [int], @YearEnd [int] 
AS

BEGIN
    DECLARE @CurrentYear INT
    SET @CurrentYear = @YearStart
    WHILE @CurrentYear IS NOT NULL AND @YearStart <= @YearEnd AND @CurrentYear <= @YearEnd
    BEGIN
        EXEC PopulateDateDimensionForYear @Year = @CurrentYear;
        SET @CurrentYear  = @CurrentYear  + 1   
    END;
END;

如您所见,第一个过程名称是 PopulateDateDimensionForYear ,我在第二个过程中将其称为 PopulateDateDimensionForYear ,它运行良好。由于只有一年的详细信息是正确的。

CREATE OR ALTER PROCEDURE [PopulateDateDimensionForYear] @Year [int] AS

BEGIN
    IF OBJECT_ID('tempdb..#month', 'U') IS NOT NULL
        DROP TABLE #month
    CREATE TABLE #month (
        monthnum int,
        numofdays int
    )
    INSERT INTO #month
        SELECT 1, 31 UNION SELECT 2, CASE WHEN (@YEAR % 4 = 0 AND @YEAR % 100 <> 0) OR @YEAR % 400 = 0 THEN 29 ELSE 28 END UNION SELECT 3,31 UNION SELECT 4,30 UNION SELECT 5,31 UNION SELECT 6,30 UNION SELECT 7,31 UNION SELECT 8,31 UNION SELECT 9,30 UNION SELECT 10,31 UNION SELECT 11,30 UNION SELECT 12,31

    IF OBJECT_ID('tempdb..#days', 'U') IS NOT NULL
        DROP TABLE #days
    CREATE TABLE #days (days int)

    INSERT INTO #days
        SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 UNION SELECT 13 UNION SELECT 14 UNION SELECT 15 UNION SELECT 16 UNION SELECT 17 UNION SELECT 18 UNION SELECT 19 UNION SELECT 20    UNION SELECT 21 UNION SELECT 22 UNION SELECT 23 UNION SELECT 24 UNION SELECT 25 UNION SELECT 26 UNION SELECT 27 UNION SELECT 28 UNION SELECT 29 UNION SELECT 30 UNION SELECT 31

    SELECT
        CAST(CAST(monthnum AS VARCHAR(2)) + '/' + CAST([days] AS VARCHAR(3)) + '/' + CAST(@year AS CHAR(4)) AS DATE) AS [Date]
        ,DAY(CAST(CAST(monthnum AS VARCHAR(2)) + '/' + CAST([days] AS VARCHAR(3)) + '/' + CAST(@year AS CHAR(4)) AS DATE)) AS [Day]
        ,CAST(DATENAME(month, CAST(CAST(monthnum AS VARCHAR(2)) + '/' + CAST([days] AS VARCHAR(3)) + '/' + CAST(@year as char(4)) AS DATE)) AS nvarchar(10)) AS [MonthName]
        ,MONTH(CAST(CAST(monthnum as varchar(2)) + '/' + CAST([days] as varchar(3)) + '/' + CAST(@year as char(4)) AS DATE)) AS [MonthNumber]
        ,CAST(N'CY' + CAST(YEAR(CAST(CAST(monthnum as varchar(2)) + '/' + CAST([days] as varchar(3)) + '/' + CAST(@year as char(4)) AS DATE)) AS nvarchar(4)) + N'-' + SUBSTRING(DATENAME(month, CAST(CAST(monthnum as varchar(2)) + '/' + CAST([days] as varchar(3)) + '/' + CAST(@year as char(4)) AS DATE)), 1, 3) AS nvarchar(10)) AS [CalendarMonthLabel]
        ,YEAR(CAST(CAST(monthnum as varchar(2)) + '/' + CAST([days] as varchar(3)) + '/' + CAST(@year as char(4)) AS DATE)) AS [Year]
        , DATEPART(ISO_WEEK, CAST(CAST(monthnum as varchar(2)) + '/' + CAST([days] as varchar(3)) + '/' + CAST(@year as char(4)) AS DATE)) AS [ISOWeekNumber]
FROM #month m
    CROSS JOIN #days d
WHERE d.days <= m.numofdays

DROP table #month;
DROP table #days;
END;

有人知道如何在范围内的所有年份实现它吗?

你的第二个 proc returns 多个结果集因此不适用于 Copy activity。您有几个选择:1) 将您的第二个过程更改为 SELECT INTO 临时 table,然后 INSERT 进入您的主要日期维度并使用存储过程 activity 调用它:

    SELECT
        ...
INTO #tmp
FROM #month m
    CROSS JOIN #days d
WHERE d.days <= m.numofdays


INSERT yourDateDim
SELECT * FROM #tmp

或者更改您的流程以使用带有 'range' 函数的 For Each 循环来生成您的年份:

@range(2000,30)

Azure Synapse 不支持 INSERT ... EXEC,但描述了一种解决方法 here

最后我从@wBob 的回答中想出了一个主意。我放在下面了。

基本上我需要的是修改第二个过程如下:

CREATE OR ALTER PROCEDURE [PopulateDateDimensionForYearRange] @YearStart [int], @YearEnd [int] AS

BEGIN
    IF OBJECT_ID('tempdb..#date_dimension', 'U') IS NOT NULL
        DROP TABLE #date_dimension
    CREATE TABLE #date_dimension (
        Date Date,
        Day int,
        MonthName VARCHAR(30),
        MonthNumber int,
        CalendarMonthLabel VARCHAR(30),
        Year int,
        ISOWeekNumber int
    )

    DECLARE @CurrentYear INT
    SET @CurrentYear = @YearStart
    WHILE @CurrentYear IS NOT NULL AND @YearStart <= @YearEnd AND @CurrentYear <= @YearEnd
    BEGIN
        INSERT INTO #date_dimension EXEC PopulateDateDimensionForYear @Year = @CurrentYear;
        SET @CurrentYear  = @CurrentYear  + 1   
    END;
    SELECT * FROM #date_dimension 
    DROP TABLE #date_dimension
END;

其余和之前完全一样,在我的文案中activity!