锚 |
---|
DABI-1739468463194 | DABI-1739468463194 | 锚 |
---|
_GoBack | _GoBack | 锚 |
---|
ROTg-1739730776296 | ROTg-1739730776296 | 大伙是不是听说数据模型功能很强大,但是使用过程发现当有很多个SQL查询、数据源表等压根不知道应该怎么关联,同时有一系列的疑问:
...
锚 |
---|
| sBdG-1739416428184 |
---|
| sBdG-1739416428184 |
---|
|
那么这就需要来了解什么是模型的关系,以及查询时模型是如何根据设置的关联进行查询的(敲黑板!!这里还涉及一个
子图命中的概念需要大家了解了解),基于这些逻辑来辅助咱们梳理模型关系应该怎么设置得到一个更加强大有趣的数据模型。
锚 |
---|
| iGDp-1736931644497 |
---|
| iGDp-1736931644497 |
---|
|
接下来咱就来开启模型关系小课堂吧。
锚 |
---|
8s0F-1739776229735 | 8s0F-1739776229735 |
Image Removed 锚 |
---|
gfPP-1739776229739 | gfPP-1739776229739 | 锚 |
---|
xNAJ-1737009497272 | xNAJ-1737009497272 | 什么是关系
锚 |
---|
| BTSP-1737009497438 |
---|
| BTSP-1737009497438 |
---|
|
像咱平时数据库肯定是会有很多张表、或者加工处理出来很多个查询,那么在数据模型中想把这些表和查询等关联起来,就需要设置它们之间的关系。
锚 |
---|
| 1A1N-1737441976136 |
---|
| 1A1N-1737441976136 |
---|
|
那要怎么确定这些表和查询之间到底有没有关系呢,这个时候就需要从业务上去梳理梳理。以产品内置的订单模型为例:
锚 |
---|
| eNSG-1737442143953 |
---|
| eNSG-1737442143953 |
---|
|
已有表 锚 |
---|
| 9VkU-1738993578011 |
---|
| 9VkU-1738993578011 |
---|
| 产品表(products) |
锚 |
---|
| qyD4-1738993578014 |
---|
| qyD4-1738993578014 |
---|
| 产品类别表(categories) |
锚 |
---|
| xFyR-1738993578018 |
---|
| xFyR-1738993578018 |
---|
| 订单表(orders) |
锚 |
---|
| 5O3u-1738993578021 |
---|
| 5O3u-1738993578021 |
---|
| 订单明细表(orderdetails) |
锚 |
---|
| SCXQ-1738993578024 |
---|
| SCXQ-1738993578024 |
---|
| 顾客表(customers) |
锚 |
---|
| 35Tg-1738993599739 |
---|
| 35Tg-1738993599739 |
---|
|
它们之间存在的业务关系:
锚 |
---|
| Syjh-1737442340427 |
---|
| Syjh-1737442340427 |
---|
|
一种产品类别会有多个产品;
锚 |
---|
| k0KW-1738993270438 |
---|
| k0KW-1738993270438 |
---|
|
一种产品可来源于多条订单明细;
锚 |
---|
| uPnM-1737442428651 |
---|
| uPnM-1737442428651 |
---|
|
一个订单可对应多条订单明细;
锚 |
---|
| J4HO-1738992921687 |
---|
| J4HO-1738992921687 |
---|
|
一位顾客能产生多条订单记录;
锚 |
---|
| lba8-1739726837102 |
---|
| lba8-1739726837102 |
---|
|
锚 |
---|
| Wt6p-1739383759424 |
---|
| Wt6p-1739383759424 |
---|
|
因此可以得到如下图的关系连线:
锚 |
---|
| ELlt-1739726832205 |
---|
| ELlt-1739726832205 |
---|
|
每条关系都可以用一条线表示,并指示了俩端(1表示1端,*表示多端)
锚 |
---|
| u9z8-1739381365054 |
---|
| u9z8-1739381365054 |
---|
|
Image Modified 锚 |
---|
| ySAu-1738993993022 |
---|
| ySAu-1738993993022 |
---|
|
锚 |
---|
| NM5L-1737442462032 |
---|
| NM5L-1737442462032 |
---|
|
这样,基于上述业务逻辑的梳理,我们就已经得知了订单模型中各表之间的联系,接下来,就可以在数据模型中深究关系的配置及原理了。
锚 |
---|
| 1sV8-1737009669767 |
---|
| 1sV8-1737009669767 |
---|
|
关系组成四大要素
锚 |
---|
| eekc-1737009672866 |
---|
| eekc-1737009672866 |
---|
|
那要在数据模型里构成关系,咱就可以了解下构成表关系的这四大要素:表(维表、事实表)、连接字段(列)、基数、筛选方向。
锚 |
---|
| jd7w-1738995567679 |
---|
| jd7w-1738995567679 |
---|
|

锚 |
---|
| toC7-1739001859651 |
---|
| toC7-1739001859651 |
---|
|
一:表(维度表、事实表)
锚 |
---|
| Usqv-1737009798776 |
---|
| Usqv-1737009798776 |
---|
|
这里的表可以叫主键表、外键表,在数据模型中我们通常把他叫做维度表、事实表。我们经常能看到,数据模型里的表有的是蓝色有的是绿色,这就是咱用来初步区分维表和事实表的颜色标识。其中,
锚 |
---|
| wtYI-1739002305629 |
---|
| wtYI-1739002305629 |
---|
|
蓝色是维度表,代表没有度量的表。如:产品表、客户表、员工表等包含一些属性特性,比如产品具有颜色、类别、成本等;
锚 |
---|
| Rn3f-1739002320968 |
---|
| Rn3f-1739002320968 |
---|
|
绿色是事实表,代表有度量的表。如销售记录表等涉及某些维度事件记录的可度量数据,比如销售额、销售量等。
锚 |
---|
| ojN1-1739002815095 |
---|
| ojN1-1739002815095 |
---|
|
表在数据模型中也会叫做查询,目前有9种类型可选,包含数据源表、SQL查询等。在模型视图中,"一"方代表维度表,"多"方代表事实表。
需要注意:由于是动态建模,在查询时根据勾选的字段,维表也可能会变成事实表。 锚 |
---|
| e2vu-1739002257970 |
---|
| e2vu-1739002257970 |
---|
|
Image Modified 锚 |
nUlj-1739001860519nUlj-1739001860519 |
二:连接字段
...
对关系的连接线段"双击"或者"右键编辑",可以修改连接字段、基数和筛选方向。
锚 |
---|
i91r-1739009597782 | i91r-1739009597782一般关系中的连接字段是以表的主键或者外键来建立联系的,目前Smartbi会自动识别主键和外键,确定两个表之间关联字段,通过获取字段名,然后逐个匹配,查找别名相同的列且数据类型要一致,才会自动关联。
锚 |
---|
| NgFr-1739003483331 |
---|
| NgFr-1739003483331 |
---|
|
Image Modified
锚 |
---|
| EQzd-1739001860532 |
---|
| EQzd-1739001860532 |
---|
|
此外,在设置连接字段时,如果发现原始表中缺少必要的关联键或者需要基于现有字段计算出新的关联键,比如想要关系字段需要使用contact、replace等函数进行拼接、替换等,可以通过自定义计算列加工出来。
锚 |
---|
| doDR-1739151982364 |
---|
| doDR-1739151982364 |
---|
|
Image Modified
锚 |
---|
| Up6H-1739001861072 |
---|
| Up6H-1739001861072 |
---|
|
三:基数
锚 |
---|
| xwkt-1739001861081 |
---|
| xwkt-1739001861081 |
---|
|
基数也就是1和*,能用来反映真实业务数据之间联系,数据模型中的基数类型有:一对一、一对多、多对一(不支持多对多)。
锚 |
---|
| YRpW-1739155835359 |
---|
| YRpW-1739155835359 |
---|
|
基数的选择是决定模型关系设置是否正确的关键之一,很多小伙伴在前期错误的设置了基数关系,那后来数据动态变化了不满足基数选择就经常会出现查询数据错误的情况了。这就要求咱们在选择基数关系时,需要理解真实业务,判断真实业务之间是一对一、一对多还是多对多的联系。
锚 |
---|
| dNww-1739377868691 |
---|
| dNww-1739377868691 |
---|
|
那其实Smartbi产品上可通过"自动检测表关系"或手动点击"检测关系"的功能来辅助我们确定两表之间的关系。它检测的原理是:
锚 |
---|
| KmbL-1739378297689 |
---|
| KmbL-1739378297689 |
---|
|
逐个判断查询相同别名的字段列,是1还是多;当count()的数量和distinct count()的数据不一致,说明该列是"多",否则为"1"。
锚 |
---|
| yg9e-1739378327666 |
---|
| yg9e-1739378327666 |
---|
|
例如:orders 与orderDetail 表,关联字段是OrderID,当orders 的count(
)与distinct count(OrderID),是一致的,则认为是"一"的一方;当orderDetail的count()与distinct count(OrderID)不是一致时,则认为是"多"的一方。
锚 |
---|
| umMe-1739378328395 |
---|
| umMe-1739378328395 |
---|
|
注意:这个检测方法会做一次count,所以数据库执行count慢时,会出现检测性能问题;自动构建表关系就是依赖基数检测结果,如果数据量很大时,建议关闭自动检测基数。
锚 |
---|
| bgtL-1739378251596 |
---|
| bgtL-1739378251596 |
---|
|
Image Modified
锚 |
---|
| QwYa-1739001861084 |
---|
| QwYa-1739001861084 |
---|
|
虽然产品目前并不直接支持多对多关系,但遇到多对多关系场景时,我们可以采用星型架构设计原则,而不是直接关联事实类型表。 一般可以通过添加维度表来实现, 然后,维度类型表通过使用一对多关系与事实类型表关联。 通过这种设计方法,可使用任何维度类型列进行筛选或分组,并汇总任何相关联的事实类型表。(具体示例见下篇-"示例3、多对多")
锚 |
---|
| HdLE-1739378137555 |
---|
| HdLE-1739378137555 |
---|
|
四:筛选方向
锚 |
---|
| nLZr-1739002612097 |
---|
| nLZr-1739002612097 |
---|
|
筛选方向定义的是维度之间过滤方向,在模型视图中用箭头表示,A->B代表A中的维度可以筛选B中的数据,而B中的维度不可以筛选A中的数据。
锚 |
---|
| ZzQB-1739378498949 |
---|
| ZzQB-1739378498949 |
---|
|
筛选方向包含了单向和双向,在这里筛选方向结合基数一起更好做理解:
...
RIMY-1739378588063 | 锚 |
---|
Dqx1-1739378588067 | Dqx1-1739378588067 锚 |
---|
wRU9-1739378588070 | wRU9-1739378588070 | 假设A与B表相关联 |
锚 |
---|
| YfsT-1739378588074 |
---|
| YfsT-1739378588074 |
---|
| 一对多 | 锚 |
---|
| b0NW-1739378588077 |
---|
| b0NW-1739378588077 |
---|
| 单向、双向 锚 |
---|
| UgXm-1739378588079 |
---|
| UgXm-1739378588079 |
---|
| 默认:单向 | 锚 |
---|
| PJPN-1739378588083 |
---|
| PJPN-1739378588083 |
---|
| A一对多B:默认A可以筛选B,B不能筛选A,如果要B筛选A,可以开启双向筛选。 |
锚 |
---|
| EFTF-1739378588089 |
---|
| EFTF-1739378588089 |
---|
| 多对一 锚 |
---|
| NBdP-1739378588091 |
---|
| NBdP-1739378588091 |
---|
|
| 锚 |
---|
| 7Tbk-1739378588094 |
---|
| 7Tbk-1739378588094 |
---|
| 单向、双向 锚 |
---|
| wBqW-1739378588096 |
---|
| wBqW-1739378588096 |
---|
| 默认:单向 | 锚 |
---|
| AWmP-1739378588099 |
---|
| AWmP-1739378588099 |
---|
| A多对一B:默认B可以筛选A,A不能筛选B,如果要A筛选B,可以开启双向筛选 |
锚 |
---|
| m5bG-1739378588103 |
---|
| m5bG-1739378588103 |
---|
| 一对一 | 锚 |
---|
| pp04-1739378588106 |
---|
| pp04-1739378588106 |
---|
| 单向、双向 锚 |
---|
| Xbba-1739378588109 |
---|
| Xbba-1739378588109 |
---|
| 默认:双向 | 锚 |
---|
| V7Wf-1739378588112 |
---|
| V7Wf-1739378588112 |
---|
| A一对一B:默认(双向)A可以筛选B,B可以筛选A;如果是单向时,根据箭头方向判断,假设箭头由A指向B,代表A可以筛选B,B无法筛选A |
锚 |
---|
| URD3-1739002612100 |
---|
| URD3-1739002612100 |
---|
|
据此我们可以总结出,双向筛选与单向筛选相比,最大的区别是:双向可以在不同表/查询的维度之间创建联动,而单向只能是:一方筛选多方,不能多方筛选一方。
锚 |
---|
| OGH1-1739946165403 |
---|
| OGH1-1739946165403 |
---|
|
到这里大家是不是会有个疑问,既然双向筛选这么好两表之间都能互相联动筛选,为什么不默认开启双向筛选呢?这就不得不强调一下双向筛选的风险了:
锚 |
---|
| mJeb-1739378970506 |
---|
| mJeb-1739378970506 |
---|
|
风险一,默认双向筛选,在多个事实同时共享两个不同维度时,会形成环路,也就是多个路径可选择,出现关系歧义;
锚 |
---|
| QbXY-1739930957025 |
---|
| QbXY-1739930957025 |
---|
|
Image Modified
锚 |
---|
| Z2hr-1739947186036 |
---|
| Z2hr-1739947186036 |
---|
|
风险二,双向筛选,会使得查询多判断一个筛选子图,可能会对数据模型的查询性能产生负面影响。
锚 |
---|
| hVVE-1739928849007 |
---|
| hVVE-1739928849007 |
---|
|
Image Modified
锚 |
---|
| qyDp-1739928553235 |
---|
| qyDp-1739928553235 |
---|
|
总之对于双向筛选,不要盲目开启,建议是按需启用哦。
锚 |
---|
| H41b-1739001866537 |
---|
| H41b-1739001866537 |
---|
|
查询性能提升的秘密武器:子图 锚 |
---|
| JwTL-1739001866547 |
---|
| JwTL-1739001866547 |
---|
|
前面其实我们也一直有提到子图这个概念,那么到底什么是子图呢,终于到了给大家介绍这个用来保证性能提升的秘密武器啦。
锚 |
---|
| FYvp-1739379170447 |
---|
| FYvp-1739379170447 |
---|
|
子图是在我们设置好关系之后,在前端分析的时候执行引擎查询哪些表。可以把子图理解为扩展表,也可以理解为数据模型中的每个表都可构建一个子图,A表的子图是以A表为中心,根据筛选方向即
箭头指向它的代表能筛选它的表,都会把它纳入子图中。
锚 |
---|
| KDEj-1739379710724 |
---|
| KDEj-1739379710724 |
---|
|
在Smartbi中,我们可以通过数据模型视图中右键菜单选择"构建布局"来快速查看子图。
锚 |
---|
| f0nr-1739379924920 |
---|
| f0nr-1739379924920 |
---|
|
Image Modified
锚 |
---|
| 2x14-1739379923550 |
---|
| 2x14-1739379923550 |
---|
|
以产品内置的订单模型中部分表为例:
...
- 1.顾客表的子图,通过构建布局可以看到,没有指向它的表,它的子图就是它自己
锚 |
---|
| Bg2B-1739379983981 |
---|
| Bg2B-1739379983981 |
---|
|

锚 |
---|
| b0yT-1739379878683 |
---|
| b0yT-1739379878683 |
---|
|
...
- 2.订单表的子图,通过构建布局可以看到,指向它的表,是:顾客表以及它自己
锚 |
---|
| 1TQa-1739727604817 |
---|
| 1TQa-1739727604817 |
---|
|

锚 |
---|
| BQyq-1739380035555 |
---|
| BQyq-1739380035555 |
---|
|
锚 |
---|
2QKH-1739933912554 | 2QKH-1739933912554 | - 3.订单明细表的子图,通过构建布局可以看到,指向它的表,是: 所有的表,因为所有的表都可以到达它
锚 |
---|
| weYL-1739727789823 |
---|
| weYL-1739727789823 |
---|
|
Image Modified 锚 |
---|
| KKO3-1739380176694 |
---|
| KKO3-1739380176694 |
---|
|
锚 |
---|
| uW7o-1739933919632 |
---|
| uW7o-1739933919632 |
---|
|
每个子图,我们可以理解为以
"多" 方 left join "一"方 构建子图查询。至于命中的是哪个子图,则会结合数据模型的动态建模,根据勾选的字段进行建模来完成查询。
锚 |
---|
| sQeg-1739728843377 |
---|
| sQeg-1739728843377 |
---|
|
比如上述这个订单模型,勾选顾客表的公司类型以及订单表的订单量 ,可以看到生成的SQL语句中,是命中了订单表这个子图;且顾客表为1方,订单表为多方,执行sql关联查询是 orders left join customers
锚 |
---|
| C89P-1739729545954 |
---|
| C89P-1739729545954 |
---|
|
Image Modified
锚 |
---|
| 9nqm-1739729048246 |
---|
| 9nqm-1739729048246 |
---|
|
这样做的好处是:在查询时,会根据用户所选维度、度量、条件,从数据模型中,动态查找相关表及其子图,基于命中后的子图再查数,能排除其他无关表,避免出现肥模型每次查询很多张表关联查询性能慢的情况。
锚 |
---|
| Q6q7-1739728446086 |
---|
| Q6q7-1739728446086 |
---|
|
因此查询性能的关键,就落到了命中的子图本身的查询性能,和整个数据模型关系不大或者说是固定消耗(除非模型超大,模型定义的解析会消耗较多时间)。
锚 |
---|
| GW5h-1739380192812 |
---|
| GW5h-1739380192812 |
---|
|
锚 |
---|
C0gq-1739859325013 | C0gq-1739859325013 |
以上就是模型关系组成元素的介绍啦!下篇我们将给大家带来模型关系设置的一些实际应用。 锚 |
---|
g0YS-1739862032805 | g0YS-1739862032805 | 锚 |
---|
V7O4-1739862174360 | V7O4-1739862174360 | 还记得《欢迎来到被数据模型统治的Smartbi》结尾留下的热身题目吗?若还没解答出来,不妨试试看文中提到的方法,看看是否能解决你的问题,并在评论区告诉我们!下篇即将揭晓具体答案。 锚 |
---|
lnra-1739862353888 | lnra-1739862353888 | 锚 |
---|
JY7b-1739862032958 | JY7b-1739862032958 | 感谢大家的支持与阅读,敬请期待下篇内容! 锚 |
---|
Bbxd-1739420743297 | Bbxd-1739420743297模型关系设置的一些实际应用可移步到Smartbi进一步学习:https://my.smartbi.com.cn/thread-11464-1-1.html