正如其名,这些是陷阱。如果我们有鸿沟或扇形陷阱,那么我们就有了一个严重的问题,因为这些可能会影响整个数据模型。
鸿沟和扇形陷阱导致笛卡尔数据。
1.扇形陷阱:在扇形陷阱中,模型最终会在两个以上的表中出现“一对多关系”,例如一个客户有多个订单,一个订单有多个订单产品,这在逻辑上是可以的,但如果创建物理数据模型,就会出现问题。
1)一对多订单的客户。
2)如果订单与订单产品之间是“一对多”的关系,则存在扇形连接问题。
Ø问题:在这种情况下,订单Id(Pkey)已经被添加到订单产品表中作为Fkey,这意味着订单产品表中将存在低基数,这意味着产品表中将存在产品的重复,这是错误的方法。在产品表中,产品ID应该是唯一的。
Ø解决方案:一个产品可以有多个订单,但反过来不行。正确的方法是在订单产品表中使用产品ID(Pkey)作为订单表中的Fkey。
2.鸿沟陷阱:在鸿沟陷阱(Chasm Trap)中,模型最终在两个以上的表中具有“多对一”的关系,例如,一个员工有许多销售交易,同一个员工也可以有许多目标交易,这在逻辑上和物理上都是可以的,但是如果我们尝试在一个查询中连接这三个表,就会出现鸿沟陷阱(Chasm Trap)。
Ø问题:在这种情况下,问题不是数据模型,而是编写查询。考虑员工表中有员工姓名John。
ü他有两个目标要实现,例如,
1)For Product 1 = Target USD 1M,
2)For Product 2 = Target USD 2M.
ü现在,他总共完成了10笔销售交易,每笔交易平均为10,000美元,目前为止他已经实现了10万美元的销售额。
ü现在,如果我们通过查询提取10万美元的信息,并将这3个表连接在一个查询中,将会发生以下情况。
ü查询将会将员工表与目标表连接,并在内存中处理2行数据,即,
vRow1: John with Target of USD 1M for Product 1
vRow2: John with Target of USD 2M for Product 2
ü现在,查询在内存中有2行要与销售表连接。现在,它将使用John作为键将这2个John与销售表连接,这就是将发生的事情。
vJohn [Product 1] will join with 10 rows in Sales and will generate 10 Rows.
vJohn [Product 2] will join with 10 rows in Sales and again will generate 10 Rows.
ü因此,总共会生成20行,这是错误的,因为现在总目标达成将显示为20万美元,而不是10万美元,这是错误的。
ü问题是笛卡尔结果。
Ø解决方案:处理这种情况有两种方法
1)分别编写两个查询
2)在一个查询中写两个子查询,并使用UNION ALL。
让我们选择第二种方法,并通过例子来理解。
ü第一个查询将连接员工表与目标表,并在内存中处理2行数据,即,
vRow1: John with Target of USD 1M for Product 1
vRow2: John with Target of USD 2M for Product 2
ü第二个查询将连接员工表与销售表,并在内存中处理10行数据,
vRow1: John with Sales of USD 10k for Product 1
vRow2: John with Sales of USD 10k for Product 2
v......
vRow10: John with Sales of USD 10k for Product 2
ü现在,使用UNION ALL连接这两个查询,你会看到12行。
ü正确结果。
创建数据模型的第一步应该是了解数据流,这定义了数据存储的方式。
提取数据的第一步是具备数据模型的业务知识。
在方程式中,交易表必须是“多”,而主/参考表必须是“一”,不可忘记这一点。