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

Posted

技术标签:

【中文标题】在 Azure 突触分析中创建日期维度【英文标题】:Create date dimension in Azure synapse analytics 【发布时间】:2021-09-08 16:05:36 【问题描述】:

我使用 2 个存储过程在 Synapse 中创建一个 date_dimension。第一个 proc 创建年份的详细信息,第二个 proc 对其进行迭代以通过复制活动创建一系列年份。

第二个过程有 2 个导入参数,即 YearStart=2000 和 YearEnd=2030。但是,当我执行复制活动时,它只会为 一年 (2000) 创建日期表 only,而且循环似乎不起作用!

这是第二个过程。

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;

如您所见,第一个 proc 名称是 PopulateDateDimensionForYear ,我在第二个 proc 中将其称为它,它运行良好。因为只有一年的细节是正确的。

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 PopulateDateDimensionForYear 的代码。 我试过你的代码,结果似乎是正确的。 ScreenShoot. 你如何从 Synapse Pipelines 调用它?我猜你在某处硬输入了参数。另请注意,此代码均未将数据插入任何日期维度 - 您是否将其作为 Sink 活动的一部分?如果这些对象与日期维度在同一个数据库中,我将只使用存储过程任务而不是复制活动来执行此操作。 @wBob 在一个复制活动中我选择了存储过程作为源,然后我选择了第二个 proc 来执行,点击 IMPORT PARAMETERS 它会自动识别参数并且我只设置它们的值。 @Ehsan 抱歉,我使用的是 Azure SQL。让我试试 Azure Synapse。 【参考方案1】:

您的第二个 proc 返回多个结果集,因此不适用于 Copy 活动。您有几个选择:1) 将您的第二个 proc 更改为 SELECT INTO 一个临时表,然后将 INSERT 更改为您的主要日期维度并使用 Stored Proc 活动调用它:

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


INSERT yourDateDim
SELECT * FROM #tmp

或者更改您的流程以使用带有“范围”功能的 For Each 循环来生成您的年份:

@range(2000,30)

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

【讨论】:

FOREACH 中的活动是什么? 存储过程活动。即不是循环之一。传入年份参数。 感谢您的帮助,但我不明白结果保存在哪里?我的意思是在复制活动中,我复制数据集中的年份,但在这里我只运行 Proc 30 次!!! 我所做的是从 proc 中创建一个文件,然后在其上创建一个视图。所以稍后我可以在 powerBI 中将该视图用作 date_dimension 更改存储过程以实际插入数据或在循环内使用 Copy 活动,类似于您最初所做的。【参考方案2】:

最后我从@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;

其余的和以前完全一样,在我的复制活动中!

【讨论】:

以上是关于在 Azure 突触分析中创建日期维度的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 中创建具有数十年的日期维度?

Azure 突触分析 |用户“<token-identified principal>”登录失败

DAX - 根据事实表中的最新数据运行日期在日期维度表中创建滚动的“过去 7 天内”TRUE/FALSE 列

无法在 OBIEE 12c 中创建具有不一致维度的多学科领域分析

外键约束 Synapse Azure

如何使用 C# 中的 Nuget 包在谷歌分析中创建自定义维度和自定义指标