微软BI 之SSAS 系列 - 自定义的日期维度设计

2023-10-20 11:20

本文主要是介绍微软BI 之SSAS 系列 - 自定义的日期维度设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

微软BI 之SSAS 系列 - 自定义的日期维度设计

2013-12-22 18:34 by BIWORK, 4562 阅读, 14 评论, 收藏, 编辑

SSAS Date 维度基本上在所有的 Cube 设计过程中都存在,很难见到没有时间维度的 OLAP 数据库。但是根据不同的项目需求, Date 维度的设计可能不大相同,所以在设计时间维度的时候需要搞清楚几个问题:

  1. 你的业务涉及到的最低的细节级别是什么?比如按季度查看报表还是按月份,或者按周,或者再甚者按天。这个细节级别需要弄清楚,比如在一些销售数据统计,有的时候可能更多按季度或者按月来查看报表。但在有的监控一些机器运行数据的统计,可能会按照小时或者分钟来查看报表。
  2. 你的报表所需要时间显示的格式是什么,比如在英文系统中客户是希望显示月份的全称 January 或者简称 Jan 或者只喜欢看到数字1212 这种类型。包括显示具体天的时候是希望看到 10/1/2005 还是 2005/10/01 等格式。
  3. 还有没有一些特别的时间信息比如不仅仅需要自然年,而且还需要财年信息,以及其它是否是闰年,周末等这样的要求。
  4. 最重要的一点是客户喜欢按照哪一种或者哪几种层次结构来查看报表,比如第一层是年,通过年导航到月再导航到日期;还是说通过年直接导航到周再到具体的日期。

弄清楚上面这几方面的内容之后,心里大概知道时间属性的范围了,细到哪一种级别,由哪些特别的字段需要添加都在这个设计阶段完成。

一般情况下,可以自己写一个创建时间日期的数据仓库维度表,在这个脚本里面可以根据需要自定义一些特别的日期格式。

---------------------------------------------------------------------
-- BIWORK DimDate and vDimDate Demo
-- http://www.cnblogs.com/biwork 
----------------------------------------------------------------------
USE BIWORK_SSIS
GO  
SET NOCOUNT ON IF OBJECT_ID('DimDate','U') IS NOT NULL
DROP TABLE DimDate
GOCREATE TABLE DimDate
(DateKey INT PRIMARY KEY,FullDate DATE NOT NULL,[DateName] NVARCHAR(20),DayNumberOfWeek TINYINT NOT NULL,DayNameOfWeek NVARCHAR(10) NOT NULL,DayNumberOfMonth TINYINT NOT NULL,DayNumberOfYear SMALLINT NOT NULL,IsWeekend BIT NOT NULL,IsLeapYear BIT NOT NULL,WeekNumberOfYear TINYINT NOT NULL,EnglishMonthName NVARCHAR(10) NOT NULL,MonthNumberOfYear TINYINT NOT NULL,CalendarQuarter TINYINT NOT NULL,CalendarSemester TINYINT NOT NULL,CalendarYear SMALLINT NOT NULL, FiscalQuarter TINYINT NOT NULL,FiscalSemester TINYINT NOT NULL,FiscalYear SMALLINT NOT NULL 
)DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIMESELECT @StartDate = '2005-01-01',@EndDate = '2013-12-31'WHILE (@StartDate <= @EndDate)
BEGININSERT INTO DimDate (DateKey,FullDate,[DateName],DayNumberOfWeek,DayNameOfWeek,DayNumberOfMonth,DayNumberOfYear,IsWeekend,IsLeapYear,WeekNumberOfYear,EnglishMonthName, MonthNumberOfYear,CalendarQuarter,CalendarSemester,CalendarYear, FiscalQuarter,FiscalSemester,FiscalYear )SELECT CAST(CONVERT(VARCHAR(8),@StartDate,112) AS INT) AS DateKey,CONVERT(VARCHAR(10), @StartDate,20) AS FullDate,CONVERT(VARCHAR(20), @StartDate,106) AS [DateName],DATEPART(DW,@StartDate) AS DayNumberOfWeek,DATENAME(DW,@StartDate) AS DayNameOfWeek,DATENAME(DD,@StartDate) AS [DayOfMonth],DATENAME(DY,@StartDate) AS [DayOfYear],CASE WHEN DATEPART(DW,@StartDate) IN (1,7)  THEN 1ELSE 0 END AS IsWeekend,CASE WHEN ((YEAR(@StartDate) % 4 = 0) AND (YEAR(@StartDate) % 100 != 0 OR YEAR(@StartDate) % 400 = 0))THEN 1ELSE 0END AS IsLeapYear,DATEPART(WW,@StartDate) AS WeekNumberOfYear,DATENAME(MM,@StartDate) AS EnglishMonthName,DATEPART(MM,@StartDate) AS MonthNumberOfYear,DATEPART(QQ,@StartDate) AS CalendarQuarter,CASE WHEN DATEPART(MM,@StartDate) BETWEEN 1 AND 6THEN 1ELSE 2END AS CalendarSemester,DATEPART(YY,@StartDate) AS CalendarYear, CASE WHEN DATEPART(MM,@StartDate) BETWEEN 1 AND 6THEN DATEPART(QQ,@StartDate) + 2ELSE DATEPART(QQ,@StartDate) - 2END AS FiscalQuarter,CASE WHEN DATEPART(MM,@StartDate) BETWEEN 1 AND 6THEN 2ELSE 1END AS FiscalSemester,CASE WHEN DATEPART(MM,@StartDate) BETWEEN 1 AND 6THEN DATEPART(YY,@StartDate) ELSE DATEPART(YY,@StartDate) + 1END AS FiscalYearSET @StartDate = @StartDate + 1
END
GO---------------------------------------------------------------------
-- 加上视图的作用是因为在实际的项目开发中,SSAS 的数据源视图所有的表对象
-- 应该都引用视图,这样当数据仓库中维度表或者事实表有小的改动就可以直接在
-- 视图中修改,而可以避免修改 SSAS 项目。
-- 这一点在 SSIS 开发中同样适用,所有在 SSIS 中配置的 SQL 语句都封装在存储
-- 过程中,表封装在视图中。逻辑的修改直接体现在存储过程中,而不会修改 SSIS。
----------------------------------------------------------------------

 

不带世纪数位 (yy)带世纪数位 (yyyy)输入/输出
-0 或 100mon dd yyyy hh:miAM(或 PM)
11011 = mm/dd/yy

101 = mm/dd/yyyy

21022 = yy.mm.dd

102 = yyyy.mm.dd

31033 = dd/mm/yy

103 = dd/mm/yyyy

41044 = dd.mm.yy

104 = dd.mm.yyyy

51055 = dd-mm-yy

105 = dd-mm-yyyy

61066 = dd mon yy

106 = dd mon yyyy

71077 = Mon dd, yy

107 = Mon dd, yyyy

8108hh:mi:ss
-9 或 109mon dd yyyy hh:mi:ss:mmmAM(或 PM)
1011010 = mm-dd-yy

110 = mm-dd-yyyy

1111111 = yy/mm/dd

111 = yyyy/mm/dd

1211212 = yymmdd

112 = yyyymmdd

-13 或 113dd mon yyyy hh:mi:ss:mmm(24h)
14114dd mon yyyy hh:mi:ss:mmm(24h)
-20 或 120yyyy-mm-dd hh:mi:ss(24h)
-21 或 121yyyy-mm-dd hh:mi:ss.mmm(24h)
-126yyyy-mm-ddThh:mi:ss.mmm(无空格)
-127yyyy-mm-ddThh:mi:ss.mmmZ(无空格)
-130dd mon yyyy hh:mi:ss:mmmAM
-131dd/mm/yyyy hh:mi:ss:mmmAM

 



=====================================================
IF OBJECT_ID('vDimDate','V') IS NOT NULL
DROP VIEW vDimDate
GOCREATE VIEW vDimDate
AS-- 可以根据需要实现一些计算列,这些计算列通常也可以在 SSAS 视图中添加。
SELECT DateKey AS 'DateKey',FullDate AS 'FullDate',[DateName] AS 'DateName',CONVERT(VARCHAR(2),DayNumberOfMonth) + ' ' + EnglishMonthName + ' ' + CONVERT(CHAR(4), CalendarYear) AS 'FullDateName', -- 1 July 2005 DayNumberOfWeek AS 'DayNumberOfWeek',DayNameOfWeek AS 'DayNameOfWeek',DayNumberOfMonth AS 'DayNumberOfMonth',DayNumberOfYear AS 'DayNumberOfYear',CASE WHEN IsWeekend = 1 THEN 'Weekend' ELSE 'Weekday'END AS 'WeekdayWeekend',IsLeapYear AS 'IsLeapYear',WeekNumberOfYear AS 'WeekNumberOfYear',EnglishMonthName AS 'EnglishMonthName',EnglishMonthName + ' ' + CONVERT(CHAR(4),CalendarYear) AS 'MonthName',  -- July 2005CalendarYear * 100 + MonthNumberOfYear AS 'MonthKey', -- 200507MonthNumberOfYear AS 'MonthNumberOfYear',CalendarQuarter AS 'CalendarQuarter',CalendarSemester AS 'CalendarSemester',CalendarYear AS 'CalendarYear',  CalendarYear * 100 + CalendarQuarter AS 'CalendarQuarterKey',  -- 200503'CY ' + CONVERT(CHAR(4),CalendarYear) AS 'CalendarYearName', -- CY 2005'CY ' + CONVERT(CHAR(4),CalendarYear) + ' Qtr ' + CONVERT(CHAR(1), CalendarQuarter) AS 'CalendarQuarterName', -- CY 2005 Qtr 3  FiscalQuarter AS 'FiscalQuarter',FiscalSemester AS 'FiscalSemester',FiscalYear AS 'FiscalYear', FiscalYear * 100 + FiscalQuarter AS 'FiscalQuarterKey', -- 200601'FY ' + CONVERT(CHAR(4), FiscalYear) AS 'FiscalYearName',  -- FY 2006'FY ' + CONVERT(Char(4), FiscalYear) + ' Qtr ' + Convert(Char(1), FiscalQuarter) AS 'FiscalQuarterName' -- FY 2006 Qtr 1
FROM DimDate
GO

在我的这个示例中,财年是以微软的财年为例子的。比如20087是自然月,但是财年就被称为 2009财年的1月,它是从每年的7月开始算的。 下面的这幅图主要是展示了各个字段上时间日期的格式是以及字段类型等。并且在后面设计维度的时候,我们往往选择 Key 会考虑使用整形数据字段,但是在 Name Column 的时候就会使用具体的描述内容。 Attribute Type 后面也能看得到,它的主要作用是为具体的时间日期字段指定日期属性。日期属性的指定能够让 SSAS Cube 在内部聚合的时候知道某个字段的含义,这个字段是描述日期,还是年还是月。在 MDX 的时间相关的层级导航或者查询中,比如说 YTD() 函数的使用就跟设置属性为 Year 相关的维度属性相关,可以参考我的这篇 MDX笔记。

新建一个 SSAS 项目并创建好数据源和数据源视图,数据源视图中就是上面创建的视图。

创建一个简单的时间维度,选择 vDimDate,并在 Key Column 中选择 DateKey, Name Column 选择 FullDateName。实际上,这里就一个属性,但是这个属性是由两部分组成的,一个是 KEY 一个是 NAME。

然后选择其它的相应的属性,这里面基本上都是选择的数值类型的属性,因为我们一会还要修改它们,为他们配置相应的 Name Column - 提供信息标签。我们同时为这些属性选择好相应的 Attribute Type,如下图所示。

修改维度名称 Date ,那么保存后就可以看到一个维度和它的维度属性了。

Date 维度它的类型会自动设置为 Time 的,不是 Time 类型的维度在 MDX 的查询中有很多时间函数可能就无法使用了。并且在 SSAS Cube 的处理过程中,就不会把这个维度当作特殊的时间维度去考虑,因此这里会自动设置为 Time 类型。

这样的结构就是一个维度和它下面的维度属性,如果仅这样部署到 SSAS 分析服务中,我们将看到的是一堆数字 KEY 表示的信息,那么这些数据就失去了"信息"的意义。

因此我们需要按照这个图来修改每一个属性,为它们指定相应的 NAME Column,这样相当于为这个数字添上了一个标签。

如上图所示,下图中的 CalendarYear 这个属性,它的 Key Column 就是 CalendarYear ,它的 Attribute Type 是 Year, 它的 Name Column 是 Calendar Year Name。

按照上面的配置修改完维度属性之后,也将名字改的简单一些。

部署之后可以看到每一个维度属性的 Name Column 展示出来的信息了,并且注意在 SSAS 中有这样的一个概念 - 维度中的属性实际上指的属性层次结构,每一个属性层次结构都包含两层。第一层是以 ALL 为代表的成员,第二层是以各个属性值表示的成员。ALL 表示的就是对下面所有属性的一个聚合,在和度量值结合起来看就会很容易理解的。

维度其实就是属性和层次结构组成的,但是除了上面的属性层次结构之外,还包括下面的用户自定义层次结构。那么这种主要是根据用户的需求来决定的,比如用户通常会根据年来聚合,或者再细看季度方面的数据,然后再是月或者天。因此下面创建两个日期自定义层次结构,一个是自然年度的,一个是财年年度的层次结构。

默认情况下,各个属性是和维度主 KEY 关联的,那么这样在层次结构关系中可能每次的上下次层次聚合都需要通过 Date Key 来进行关联,比如说不能通过 Month 来直接找到季度方面的成员,也不能通过年来找到具体季度的成员,因此需要对属性之间的关系做出一定的调整,提高 SSAS 处理属性聚合时的效率。

修改完了之后的属性关系就更加合理一些。

创建好的自定义属性层级关系,它的导航结构和上图的设计是一致的,注意到它也有一个 ALL 级别。

实际上刚才我们设计的这些个属性我们之前也一直强调过,是由两部分组成的,一部分是自身的 KEY,另一部分是 NAME 来增强了对它们自身的解释。下面描述了这些属性的 NAME 匹配关系。

这个是财年层次结构的展开效果。

财年 KEY 和 NAME 的对应关系。

但是在自然的属性层次结构中,我们看到 MONTH NAME 下面的成员顺序不正确,一月份应该是 January ,但是 April 却排到最前面去了。虽然这里的成员顺序不会影响我们数据分析,但是人们更加希望能够按照约定俗成的方式更自然的方式来展现,这样更符合我们的习惯。

因此需要编辑属性关系,我们之前偷偷加了一个属性 Month Number Of Year 但是一直没有用到,但是在这里就可以用上了。

绑定的属性关系中,可以看到 Month Name 又将 Month Number Of Year 这个属性关联成它自己的一种属性了。

Month Name 排序之前按照 Key 排序,Key 就是 Month Name 自身的英语月的排序,那么 April 肯定是显示在第一个的位置了。

注意这里要使用 Attribute Key 排序,选择 Month Number Of Year。

由于 Month Number Of Year 这个属性只是用来做排序用的,因此这个属性层次结构是没有必要展示在客户端的,也没有必要作为一个属性出现,因此禁用浏览,也禁用变成层次结构。

部署完毕之后就可以看到一个正常的月份顺序了。

下面是对应关系。

如果按照 Attribute Name 排序会出现什么问题?

可以看这幅图,如果按照 Attribute Name 来排序的话,就会看到顺序会变成 1,10,11,12 然后才是 2,3,4 ...9 。

这篇关于微软BI 之SSAS 系列 - 自定义的日期维度设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/246745

相关文章

MySQL按时间维度对亿级数据表进行平滑分表

《MySQL按时间维度对亿级数据表进行平滑分表》本文将以一个真实的4亿数据表分表案例为基础,详细介绍如何在不影响线上业务的情况下,完成按时间维度分表的完整过程,感兴趣的小伙伴可以了解一下... 目录引言一、为什么我们需要分表1.1 单表数据量过大的问题1.2 分表方案选型二、分表前的准备工作2.1 数据评估

聊聊springboot中如何自定义消息转换器

《聊聊springboot中如何自定义消息转换器》SpringBoot通过HttpMessageConverter处理HTTP数据转换,支持多种媒体类型,接下来通过本文给大家介绍springboot中... 目录核心接口springboot默认提供的转换器如何自定义消息转换器Spring Boot 中的消息

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Linux中的自定义协议+序列反序列化用法

《Linux中的自定义协议+序列反序列化用法》文章探讨网络程序在应用层的实现,涉及TCP协议的数据传输机制、结构化数据的序列化与反序列化方法,以及通过JSON和自定义协议构建网络计算器的思路,强调分层... 目录一,再次理解协议二,序列化和反序列化三,实现网络计算器3.1 日志文件3.2Socket.hpp

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

Python标准库datetime模块日期和时间数据类型解读

《Python标准库datetime模块日期和时间数据类型解读》文章介绍Python中datetime模块的date、time、datetime类,用于处理日期、时间及日期时间结合体,通过属性获取时间... 目录Datetime常用类日期date类型使用时间 time 类型使用日期和时间的结合体–日期时间(

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并