• 第8章 综合案例—构建DVD租赁商店数据仓库


    目录

    章节概要

    案例背景介绍

    数据仓库的架构模型

    数据仓库的架构模型

    数据库sakila的下载和安装 

    数据库sakila简介

    数据库sakila中 数据表之间的关系

    数据表简介 

    用于储存电影基本信息及相关介绍的数据,该数据表各个字段的含义如表。

     用于储存定义电影id所属电影类别id的数据,该数据表各个字段的含义如表。

    用于储存电影类别名称所属类别id的数据,该数据表各个字段的含义如表

    通过Kettle工具加载日期数据至dim_date日期维度表。


    章节概要

    sakila样本数据库是MySQL官方提供的一个模拟DVD租赁商店管理的数据库。本章,我们将综合运用前面几章的知识,对数据库sakila中的数据进行清洗操作,从而构建一个DVD租赁商店数据仓库系统,即实现定期从源数据库sakila中抽取增量数据,转换成符合DVD租赁业务的数据,最后加载到目标数据仓库中。

    案例背景介绍

    在日益激烈的商业竞争中,在线DVD租赁商店的决策者都迫切地需要更加准确的战略决策信息。每个在线DVD租赁商店的数据都存储在数据库中,因此该数据库中拥有海量的数据,并不缺乏足够的信息,但是这些数据并不是战略决策需要的信息。虽然这些海量数据对于在线DVD租赁商店的运作是非常有用的,但是对于商业的战略决策和目标制定的作用是微乎其微的。对于在线DVD租赁商店的决策者来说,他们需要从多个不同的商业角度观察数据,例如时间、电影、演员、用户等角度观察数据,并进行相关的分析得出决策,但是数据库中的数据不适合从多个角度进行分析,无法得出战略决策。然而,数据仓库支持复杂的分析操作,侧重于决策支持,并且还提供直观易懂的查询结果,因此我们需要基于数据库sakila创建一个DVD租赁商店数据仓库,并将sakila数据库中的数据加载到数据仓库中,便于在线DVD租赁商店的决策者对数据进行分析得出商业决策。

    数据仓库的架构模型

    数据仓库sakila_dw的架构模型是一个星型模型,其中dim_film表、dim_customer表、dim_actor表、dim_store表、dim_staff表、dim_date表以及dim_time表均为维度表;fact_rental表为事实表。

    数据仓库的架构模型

    数据库sakila的下载和安装 

    我们可以从MySQL的官网下载数据库sakila的建库脚本,若是在Windows环境下安装数据库sakila,则下载名称为sakila-db.zip的压缩包文件;若是在Linux环境下安装数据库sakila,需要下载名称为sakila-db.tar.gz的压缩包文件。 本书下载的是名称为sakila-db.zip的压缩包文件,该压缩包文件中包含三个文件,分别是文件sakila.mwb、文件sakila-data.sql和文件sakila-schema.sql。其中,文件sakila.mwb是一个MySQL Workbench数据模型,用于查看数据库结构;文件sakila-data.sql是用于创建数据库sakila的数据;文件sakila-schema.sql是用于创建数据库sakila的数据结构。

    数据库sakila下载完成后,直接解压压缩包,然后使用MySQL图形化管理软件SQLyog先运行脚本文件sakila-schema.sql创建数据库sakila和数据表,再运行脚本文件sakila-data.sql向数据库sakila中的数据表加载数据,最后刷新数据库并查看数据库sakila中的数据表及数据表中的数据,若数据表中均含有数据则说明安装数据库sakila成功,否则说明安装不成功,需要重新解压安装。 需要注意的是,安装数据库sakila之前需要下载并安装MySQL关系型数据库,并且版本不可以低于5.0,本书使用的是MySQL 8.0.16版本。关于MySQL数据库的下载安装这里不作详细介绍,读者可自行下载安装即可。

    数据库sakila简介

    数据库sakila中一共含有十六张数据表,分别是actor(演员)表、address(地址)表、category(类别)表、city(城市)表、country(国家)表、customer(顾客)表、film(电影)表、film_actor(演员所属电影)表、film_category(电影所属的类别)表、film_text(电影描述)表、inventory(库存)表、language(语言)表、payment(付款)表、rental(租赁)表、staff(工作人员)表以及store(商店)表。

    数据库sakila中 数据表之间的关系

    数据表简介 

    用于储存电影基本信息及相关介绍的数据,该数据表各个字段的含义如表。

    字段名称

    数据类型

    相关说明

    film_id

    smallint

    主键(电影id)

    title

    varchar

    电影名称

    description

    text

    电影描述

    release_year

    year

    上映年份

    language_id

    tinyint

    语言id

    original_language_id

    tinyint

    原版语言id

    rental_duration

    tinyint

    租赁时长

    rental_rate

    decimal

    电影租赁费

    length

    smallint

    电影时长

    replacement_cost

    decimal

    替换成本

    rating

    enum

    评分

    special_features

    set

    特色

    last_update

    timestamp

    最后更新时间

     用于储存定义电影id所属电影类别id的数据,该数据表各个字段的含义如表。

    字段名称

    数据类型

    相关说明

    film_id

    smallint

    主键(电影id)

    category_id

    tinyint

    外键(电影类别id)

    last_update

    timestamp

    最后更新时间

     

    用于储存电影类别名称所属类别id的数据,该数据表各个字段的含义如表

    字段名称

    数据类型

    相关说明

    name

    varchar

    类别名称

    category_id

    tinyint

    主键(电影类别id)

    last_update

    timestamp

    最后更新时间

     用于储存定义演员id所属电影id的数据,该数据表各个字段的含义如表。

    字段名称

    数据类型

    相关说明

    actor_id

    smallint

    主键(演员id)

    film_id

    smallint

    外键(电影id)

    last_update

    timestamp

    最后更新时间

    表过多 这里不一一陈述 

    我们基于数据库sakila构建一个星型模型的DVD租赁商店数据仓库,并命名为sakila_dw。数据仓库sakila_dw中的事实表fact_rental是根据数据库sakila中的数据表rental创建的;维度表是根据数据表sakila中数据表的分类创建的,即从人员、时间、地点以及事件四个角度进行创建数据仓库sakila_dw的维度表,具体如下: 从人员角度角度创建维度表dim_customer和维度表dim_staff,分别表示租赁业务中的客户和员工; 从时间角度创建维度表dim_date和维度表dim_time,用于记录所有DVD的租赁时间和归还时间; 从地点角度创建维度表dim_store,用于记录DVD光盘是从哪个商店租赁的; 从事件角度创建维度表dim_actor和维度表dim_film,其中维度表dim_actor用于记录演员的基本信息,维度表dim_film用于记录电影的基本信息。由于电影是租赁和归还的实际对象,因此维度表dim_film应与事实表fact_rental关联。一部电影是由多位演员出演,所以会有桥接表dim_film_actor_bridge,该表将电影与演员相关联。

    数据仓库sakila_dw中的每个维度表(dim_date和dim_time除外)都对应着数据库sakila中某个数据表,例如维度表dim_store对应着数据表store、维度表dim_actor对应着数据表actor。 本书为读者提供了创建sakila_dw数据仓库的SQL脚本文件,其脚本文件的名称为sakila_dw_schema.sql,读者只需要使用MySQL图形化管理软件SQLyog运行sakila_dw_schema.sql脚本文件创建sakila_dw数据仓库即可。

    通过Kettle工具加载日期数据至dim_date日期维度表。

    使用Kettle工具,创建一个转换load_dim_date,并添加生成记录控件、增加序列控件、JavaScript代码控件、表输出控件以及Hop跳连接线,具体如图所示。

    双击“生成记录”控件,进入“生成记录”配置界面。

     

     

    在“限制”处添加生成的日期,默认为10,这里改为3650,即生成10年的日期(10*365);在“字段”框添加字段language(语言)、country_code(国家码)、initial_date(初始化的日期),对生成的日期进行初始化,具体如图所示。 

     

    双击“JavaScript”控件,进入“JavaScript”配置界面,勾选“兼容模式?”处的复选框,使得JavaScript代码控件的兼容性更强;在Java Script代码框中编写代码,如图所示。 

     

     

    1. //Script here
    2. //生成locale
    3. var locale = new java.util.Locale(language.getString(),country_code.getString());
    4. //生成Calendar
    5. var calendar = new java.util.GregorianCalendar(locale);
    6. //设置时间
    7. calendar.setTime(initial_date.getDate());
    8. //设置日历为当前日期
    9. calendar.add(calendar.DAY_OF_MONTH,DaySequence.getInteger()-1);
    10. //获取日期
    11. var date = new java.util.Date(calendar.getTimeInMillis());
    12. //生成短日期
    13. var date_short = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT,locale).format(date);
    14. //生成中日期
    15. var date_medium = java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM,locale).format(date);
    16. //生成长日期
    17. var date_long = java.text.DateFormat.getDateInstance(java.text.DateFormat.LONG,locale).format(date);
    18. //生成全日期
    19. var date_full = java.text.DateFormat.getDateInstance(java.text.DateFormat.FULL,locale).format(date);
    20. //简单格式化
    21. var simpleDateFormat = java.text.SimpleDateFormat("D",locale);
    22. //天在年的第几天
    23. var day_in_year = simpleDateFormat.format(date);
    24. //建立格式器
    25. simpleDateFormat.applyPattern("d");
    26. //天在月的第几天
    27. var day_in_month = simpleDateFormat.format(date);
    28. simpleDateFormat.applyPattern("EEEE");
    29. //星期的名称
    30. var day_name = simpleDateFormat.format(date);
    31. simpleDateFormat.applyPattern("E");
    32. //星期的缩写
    33. var day_abbreviation = simpleDateFormat.format(date);
    34. simpleDateFormat.applyPattern("ww");
    35. //一年的第几周
    36. var week_in_year = simpleDateFormat.format(date);
    37. simpleDateFormat.applyPattern("W");
    38. //一月的第几周
    39. var week_in_month = simpleDateFormat.format(date);
    40. simpleDateFormat.applyPattern("MM");
    41. //月份
    42. var month_number = simpleDateFormat.format(date);
    43. simpleDateFormat.applyPattern("MMMM");
    44. //月的名称
    45. var month_name = simpleDateFormat.format(date);
    46. simpleDateFormat.applyPattern("MMM");
    47. //月的缩写
    48. var month_abbreviation = simpleDateFormat.format(date);
    49. simpleDateFormat.applyPattern("yy");
    50. //两位的年
    51. var year2 = simpleDateFormat.format(date);
    52. simpleDateFormat.applyPattern("yyyy");
    53. //四位的年
    54. var year4 = simpleDateFormat.format(date);
    55. //季度名称
    56. var quarter_name = "Q";
    57. //季度
    58. var quarter_number;
    59. switch(parseInt(month_number)){
    60. case 1:case 2:case 3:quarter_number = "1";break;
    61. case 4:case 5:case 6:quarter_number = "2";break;
    62. case 7:case 8:case 9:quarter_number = "3";break;
    63. case 10:case 11:case 12:quarter_number = "4";break;
    64. }
    65. quarter_name += quarter_number;
    66. //定义常量
    67. var yes = "yes";
    68. var no = "no";
    69. //获取周的第一天
    70. var first_day_of_week = calendar.getFirstDayOfWeek();
    71. var day_of_week = java.util.Calendar.DAY_OF_WEEK;
    72. //判断是否为周的第一天
    73. var is_first_day_in_week;
    74. if(first_day_of_week == calendar.get(day_of_week)){
    75. is_first_day_in_week = yes;
    76. }else{
    77. is_first_day_in_week = no;
    78. }
    79. //日历的下一天
    80. calendar.add(calendar.DAY_OF_MONTH,1);
    81. //获取下一天
    82. var next_day = new java.util.Date(calendar.getTimeInMillis());
    83. //判断是否周的最后一天
    84. var is_last_day_in_week;
    85. if(first_day_of_week == calendar.get(day_of_week)){
    86. is_last_day_in_week = yes;
    87. }else{
    88. is_last_day_in_week = no;
    89. }
    90. //判断是否为月的第一天
    91. var is_first_day_in_month;
    92. if(day_in_month == 1){
    93. is_first_day_in_month = yes;
    94. }else{
    95. is_first_day_in_month = no;
    96. }
    97. //判断是否为月的最后一天
    98. var is_last_day_in_month;
    99. if(java.text.SimpleDateFormat("d",locale).format(next_day)==1){
    100. is_last_day_in_month = yes;
    101. }else{
    102. is_last_day_in_month = no;
    103. }
    104. //年_季度
    105. var year_quarter = year4 + "-" + quarter_name;
    106. //年_月份
    107. var year_month_number = year4 + "-" + month_number;
    108. //年_月缩写
    109. var year_month_abbreviation = year4 + "-" + month_abbreviation;
    110. //日期代理剑(唯一键)
    111. var date_key = year4 + month_number + (day_in_month<10?"0":"") + day_in_month;

    单击【输入字段映射】按钮,弹出“映射匹配”对话框,依次选中“源字段”选项框的字段和“目标字段”选项框的字段,再单击【Add】按钮,将一对映射字段添加至“映射”选项框中,若“源字段”选项框的字段和“目标字段”选项框的字段相同,则可以单击【猜一猜】按钮,让Kettle自动实现映射,具体如图所示。 

     运行结果如下:

     navicat查看如下

  • 相关阅读:
    文件上传接口
    37.JavaScript对象与JSON格式的转换,JSON.stringify、JSON.parse方法的使用方法和注意事项
    1.6 编写双管道ShellCode后门
    HTML5中表单提交的4种验证方法
    MySQL高频面试题
    【Promise】Promise 使用 / 回调地狱问题 async-await /宏队列与微队列
    Day25力扣打卡
    pip安装numpy显示没有pip模块怎么办
    Linux关机命令、选项和原理详解
    线性代数
  • 原文地址:https://blog.csdn.net/kiritobryant/article/details/128048447