多值维度设计

在数仓建设过程中可能会遇到事实表中的一行对应维度表中多行的情况,产生多值维度,例如一个订单由多名销售人员共同完成。就此问题说一下我的设计思路

思路1:在事实表中增加多个字段来标记同一个订单的同种维度值

866791f20e09c0f0763ccefc5b1d99c1d3d.jpg

适用场景

适用于固定销售人员数量的场景

优点:

好维护,结构清晰,易理解

缺点:

只适合固定数目的场景,如果是不固定数目的销售人员,在事实表中就不知道要建立多少个销售人员的字段,且及时设置了最多的销售人员个数,就可能会造成很多字段的稀疏;

使用不方便,若希望得到某个销售人员的订单数,得遍历所有此类字段;

思路2:建立桥接表

方法1

3ff94ac66f0b2fee93ea1367d10a53ca134.jpg

方法2

40adf9e005bc3a838b79942caca744749b1.jpg

group桥接表中存放每个订单的销售人员,每个订单对应一个销售组;percent是分配因子,用于分配每个销售人员的贡献度(可以避免多重计算);方法1中primary_saleman_id放在group中,在事实表与桥接表不使用分配因子进行连接的情况下回引起多重计算,因此需要先对group表进行预处理,而在方法2中,primary_saleman_id放在order中,可以直接将order和saleman做关联,不会引起多重计算。

优点:

灵活简化了生成报表的难度

借分配因子避免了多重计算;

缺点:

桥接表的维护比较复杂,当出现一个新组合时,得先判断桥接表中是否已存在;

缓慢变化维的影响

对思路1的处理办法按照常规方式处理即可,对思路2进行处理时,一旦saleman变化的属性需要插入新记录时,该销售人员若有新的订单,就需要在group中新增一条记录。

 

 

 

 

转载于:https://my.oschina.net/u/4010291/blog/3056255

### 维度关系的处理方法 在数据建模或数据库设计中,维度关系)是一个常见的挑战。以下是几种处理维度关系的方法: #### 1. 使用桥表 桥表是一种常见的解决方案,用于解决关系问题。桥表通过将关系分解为两个一对关系来实现。桥表通常包含两个外键列,分别指向事实表和维度表,并且可以附加权重或其他属性以支持更复杂的分析需求[^4]。 例如,在一个订单系统中,如果一个订单可能包含个产品,而每个产品也可能出现在个订单中,则可以通过创建一个桥表 `order_product` 来表示这种关系: ```sql CREATE TABLE order_product ( order_id INT, product_id INT, quantity INT, PRIMARY KEY (order_id, product_id), FOREIGN KEY (order_id) REFERENCES orders(order_id), FOREIGN KEY (product_id) REFERENCES products(product_id) ); ``` #### 2. 将维度拆分为单独的行 另一种方法是将维度拆分为单独的行存储在事实表中。这种方法适用于当维度需要直接参与分析时。尽管这种方法可能会增加事实表的大小,但它简化了查询逻辑并提高了查询性能[^3]。 例如,在一个销售系统中,如果一个订单可能涉及个销售人员,则可以在事实表中为每个销售人员创建一条记录: ```sql CREATE TABLE sales_fact ( sale_id INT, date_id INT, product_id INT, salesman_id INT, amount DECIMAL(10, 2), PRIMARY KEY (sale_id), FOREIGN KEY (date_id) REFERENCES date_dimension(date_id), FOREIGN KEY (product_id) REFERENCES product_dimension(product_id), FOREIGN KEY (salesman_id) REFERENCES salesman_dimension(salesman_id) ); ``` #### 3. 使用嵌套结构(仅限特定数据库) 某些现代数据库(如NoSQL或JSON支持的关系型数据库)允许使用嵌套结构来存储维度。这种方法可以减少表的数量并简化模型,但可能会影响查询性能。 例如,在PostgreSQL中,可以使用JSONB类型来存储维度: ```sql CREATE TABLE sales_fact ( sale_id INT PRIMARY KEY, date_id INT, product_id INT, salesmen JSONB, amount DECIMAL(10, 2), FOREIGN KEY (date_id) REFERENCES date_dimension(date_id), FOREIGN KEY (product_id) REFERENCES product_dimension(product_id) ); ``` 在这种情况下,`salesmen` 列可以存储一个JSON数组,表示与该销售相关的所有销售人员。 #### 4. 创建复合维度 对于某些场景,可以将维度合并为一个复合维度。这种方法适用于当维度的组合相对固定时。然而,这种方法可能会导致维度表变得过于复杂[^5]。 例如,在一个商品系统中,如果需要同时考虑品牌和类别的维度,则可以创建一个复合维度表 `brand_category`,其中包含所有可能的品牌-类别组合: ```sql CREATE TABLE brand_category ( brand_category_id INT PRIMARY KEY, brand_id INT, category_id INT, FOREIGN KEY (brand_id) REFERENCES brand_dimension(brand_id), FOREIGN KEY (category_id) REFERENCES category_dimension(category_id) ); ``` ### 注意事项 - 在选择解决方案时,需要权衡查询性能、存储成本和模型复杂性。 - 对于OLAP系统,通常优先考虑查询效率,因此桥表和拆分行的方法更为常见。 - 如果使用嵌套结构,需确保所选数据库支持高效的JSON或类似结构的查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值