通过语义层小节的学习,相信你已经对元数据文件的制作有了初步了解,其实,元数据中除了可以做一些常规的设置外,还可以做一些高级设置,比如外键、假表层函数、子表等。在上一小节中讲述了高级设置的使用,本节将主要针对这些高级元数据设计做进一步介绍。
在元数据中可以自定义外键。与数据库中的概念相似,DQL中,表的外键字段指向另一张表的主键,从而产生关联。
Foreign key name:外键的名称可以直接编辑,设定时不允许与本表的其它外键名称相同,否则引用外键时会产生错误;如果当前外键是由单外键字段组成的,那么外键名称通常可以不使用,而是用外键字段来代替;如果当前外键是由多个外键字段组合成的,那么在引用外键指向表的字段时,只能使用Foreign key name,如上图中fk1、fk2和fk3均为外键名称,选中外键的外键名称是fk2。
Referenced table name:外键所指向的表名,当指向表的主键唯一且非外键时,那么这个表称为维表,简称维,如上图所示的维是:Product。
Referenced field:外键指向表的主键,如上图所示的引用字段是:ProductID,即ProductID是Product表的主键。
Foreign key filed:当前表的字段,和引用字段一一对应,如上图中所示Inventory表的外键字段是:ProductID
在DQL中,外键字段和维字段的地位是完全一样的,可以把外键字段看成维字段。
任何表的主键都可以视为维字段。如果某个表的主键是外键,那么这个主键的维即为外键指向的维;如果主键并非外键,那么这个主键的维就是它本身。对于非主键的字段,只有当它是外键时才是维字段,字段的维即为外键指向的维。
举例:
根据上图所示,“ReturnedPmt”表中的CustomerID字段指向“Customer”表的CustID字段,“ReturnedPmt”表与“Customer”表之间的数据关系为多对一的关系,其中的相关概念描述如下:
外键字段:“ReturnedPmt”表的CustomerID字段
维表:“Customer”表
引用字段:“Customer”表的主键CustID字段
写DQL的时候,可以像引用属性一样引用外键表的字段,比如:SELECT CustomerID.CustName,Date,Amount FROM ReturnedPmt,这里CustomerID.CustName引用的是CustomerID指向的“Customer”表的CustName字段。
知识点:
1) 对于单一字段形成的外键,在使用DQL时,可以用外键字段.外键表的字段名的方式来直接使用。
2) 对于多字段组成的外键,在使用DQL时,可以用外键名称.外键表的字段名的方式来直接使用。
3) 使用外键名称.外键表的字段名方式引用,既可用于多字段组成的外键,也可用于单一字段形成的外键情况。
在表中,参数为维的函数,且返回维与原维不同时,称为层函数。
所谓假表,就是虚表中实际不存在的单字段表。在DQL中引入假表的概念,主要是为了解决两类问题:
第一类通过定义维的各个层次结构,使用户能够在不同的粒度上观察数据。
通过假表与层函数的配合使用,我们能够定义类似于,年、年月、日期,这样的日期层次,从而使用户获得能够在不同时间粒度上观察数据的能力,同样的,我们也能够定义国家、省、市这样的结构,这取决于具体的业务规范,对于这种结构,在元数据编辑设计器中都可以一次定义,到处使用。
对于层次结构的定义,通常有几个维度就定义几张表(或假表)。比如上述的日期,一般就定义年、年月、日这样三张表。如果业务表中的日期字段存储的是日信息,就让它指向“日”表,如果是年月信息,则指向“年月”表,依次类推。
在元数据定义中,当表间的外键关系设定之后,会根据外键设定中,产生的维信息,自动生成维的相关定义。然后可以在元数据的维和层页面里,定义这几个维度间的计算关系。
举例:
日期维中定义层函数,比如demo.glmd中通过Day、Year、YearMonth三张假表定义的日期层次:
说明:
1) 在层间计算式中用?表示源字段表
,表示“Year”维年字段的值可以由“YearMonth”维的年月字段通过表达式int(?/100)换算而来。
2) 层间计算式也可以说成从细向粗计算。比如“Day”维,只能从日算出年,不能从年算出日。
3) 目标维可分别通过多个源维进行换算。比如“Year”维,可能是从日聚集到年,也可能从年月聚集到年,因此,对于“Year”维,就要定义两个层间计算式,分别从“Day”表的日期和“YearMonth”表的年月计算而来。
4) 定义好这种结构之后,我们就可以在DQL中直接使用定义中的任何结构,如下例:
在ReturnedPmt表中Date是个日期类型,在ReturnedPmt表的外键定义中,我们将“ReturnedPmt”表的字段Date与“Day”表的字段Day建立外键关系,如下图:
这样,我们就可以在DQL中获得Date的年,月等信息了,如Date#Year,得到Date的年份,Date#YearMonth就得到了Date的年月
DQL: SELECT CustomerID,ID,Date,Date#YearMonth YearMonth,Date#Year Year,Amount,SellerID FROM ReturnedPmt
DQL: SELECT sum(Amount) Sum_Amount ON Year FROM ReturnedPmt by Date#Year
DQL: SELECT sum(Amount) Sum_Amount ON YearMonth FROM ReturnedPmt by Date#YearMonth
举例:
整数维中定义层函数,比如demo.glmd中通过Province、Area、City表定义的层次:
DQL查询语句及结果:
DQL: SELECT CustID,CustName,Contact,ContactTitle,CityCode,CityCode#Province Province,CityCode#Area Area FROM Customer
DQL: SELECT count(CustID) CustNumber ON Area FROM Customer BY CityCode#Area
DQL: SELECT count(CustID) CustNumber ON Province FROM Customer BY CityCode#Province
第二类可以充当数据库视图,这种情况下,可以把假表视为表来使用,可以为其定义主键、外键等属性,在用户眼中和表是相同的。
知识点:
有了假表和层函数等概念,用户就可以按照希望的层次来观察数据,并且用户也可以更灵活的使用数据。
在元数据中,当A表中有多个主键时,对部分主键字段添加外键后,在外键对应的主表中会自动将A表做为子表列出。通过添加子表,可以在主表中直接对子表字段进行汇总查询。如Customer,根据子表ReturnedPmt,可在查询Customer表字段的同时对ReturnedPmt表中的字段做汇总查询。
部分主键字段构成外键指向的表是主表;单字段主键的层函数的维表是主表;主表的主表是主表;同维表的主表是主表;主表的同维表是主表。
注意:要求主子表的主键按次序对应,主子表还要求按主键有序。子表外键必须关联主表主键字段。
通过在元数据中添加子表,可以使相关查询语句更为精简方便。例如:
CustID为Customer表中的主键字段,ReturnedPmt中CustomerID和ID为主键字段,ReturnedPmt的CustomerID外键指向Customer表的CustID。
ReturnedPmt中外键设置如下:
在Customer表中会自动添加子表ReturnedPmt,如下:
在主表中对子表字段的汇总查询与主表中字段的查询语法不同,如:
SELECT
CustName ,
Customer@ReturnedPmt.sum(Amount) Total
FROM
Customer by CustName
知识点:
1) 在主表中可对子表字段做汇总,子表外键必须指向主表主键字段。
2) 在主表中对子表字段的汇总查询语法:
T@S.f(F) 表示表T的子表S的广义字段F的聚合表达式,f为聚合函数count/avg/sum/max/min
通过设定主键和外键,使得表与表相互关联。根据外键关联,可以获得Customer表以及与Customer表同维的VIPCustomer等表的信息。通过Employee表的外键关联,可以获得City表的信息,等等。
表的外键,同维表的外键,广义外键关联表的外键,通称为广义外键,另外,广义外键的层函数也是一种广义外键。
表的字段,同维表的字段,广义外键关联表的字段,广义字段的层函数通称为广义字段。
用广义字段定义的表达式,通称为伪字段,按普通字段处理,但不作为外键。
通过在元数据中设定伪字段,可以命名一些常用的广义字段,可以使得对它们的查询语句更为精简方便。例如:
如果在ReturnedPmt中定义广义字段VIPCustomer_End结束如下:
伪字段可以相当于普通字段使用,如查询的DQL可以写成:SELECT VIPCustomer_End FROM ReturnedPmt,而不必写为SELECT CustomerID.EndTime#YearMonth FROM ReturnedPmt。
注意:伪字段是用宏替换方式实现的,不能再使用层函数。