当所有维度值具有100%重要性时,处理多对多维度

时间:2011-03-31 04:45:04

标签: sql database-design data-warehouse dimensions

我至少会尝试保持这种简洁。

我们假设我们正在跟踪帐户余额。所以我们的事实表将包含诸如......

之类的列

帐户余额事实表

  • (FK)AccountID
  • (FK)DateID
  • ...
  • 余额
  • ...

显然,您有帐户维度表日期维度表。所以现在我们可以轻松过滤账户或日期(或日期范围等)。

但是这里是踢球者...账户可以属于组 - 给定日期的任意数量的组。组只是逻辑抽象,除了报告目的,它们没有任何实际意义。处于0,1或17组的帐户不会以任何方式影响其余额。例如,AccountID 1可以在组38,76,104和159中。帐户2可以在组1中(其具有“未组合”的组描述。帐户3可以在17个组中(实例)。

作为额外奖励,我们的用户完全不是技术性的。他们不了解SQL,他们没有关系数据库的经验,并且历史上他们在一个复杂的Excel解决方案中完成了所有工作。现在我们正在构建一个他们可以使用PowerPivot进行切片和过滤的维度模型,尽管这些帐户组有可能将其他无情的简单星型模式转变为足够复杂的东西,用户将会犹豫不决并返回当前的意大利面条解决方案。

那么让我们来看看我们的选择......

布尔方法 布尔方法不可行。我们有大约570,000个不同的帐户,但更重要的是,有26,000个不同的帐户。这也是最终用户过滤的一个魔鬼,因为它们是非技术性的,并且依靠非常简单的工具来完成这项工作。

多列方法 理论上这可行,但是,我们确实有一些属于17个群体的帐户。同样,这些组实际上只是逻辑组 - 它们没有任何意义,但它们是业务所需要的,用于报告目的。让最终用户过滤掉来自17个不同列的组不会在用户接受中过得好,并且可能导致用户拒​​绝使用该解决方案(我不会责怪他们)。

桥牌表 这个计数工作,但我们有26,000个不同的组。我发现这不是用户友好的。

由于我不喜欢我的选择,我只能假设除了雪花之外还有更好的方法......除非雪花是唯一的方法。如果有人可以伸出援助之手并解释他们的理由,我们将不胜感激。


更新:为了澄清,我认为每个人都可以参与的一个例子是想象你可以在简历上列出关键词技能。它们都与同一个人有关,但你可以拥有任何技能。这些技能不会影响简历上的任何个别措施 - 即“C ++”并不比“C#”更有价值 - 你不能将所有的简历/技能组合放在事实表中,否则你就会结束重复计算(或者超过两倍;))。

我认为我能够在这里做的最好的事情是为群组创建一个支腿表。我不是它的粉丝,但我认为这是我唯一真正的选择。

所以我们现在......

帐户余额事实表

  • (FK)AccountID
  • (FK)DateID
  • ...
  • 余额
  • ...

帐户维度

  • (PK)的AccountID
  • 帐户名称
  • ...
  • (FK)帐户组密钥

帐户组支腿

  • (PK)AccountGroupID
  • (PK)的AccountID)
  • 帐户组名称

2 个答案:

答案 0 :(得分:1)

我会说你必须从界面开始。用户如何在理想的世界中进行过滤?

我想我最终会选择一个桥梁或无事实的事实表或类似的东西。也许是事实表上的代理键和从组到成员身份的许多链接表。

这绝对是艰难的 - 接口和使用案例必须变得可行,所以我从那里开始。也许某些事情会影响他们如何进行此报告 - 例如组中的等价类或者他们对帐户空间进行划分的方式。也许组织的层次结构或组织使其更易于管理,并可以通知更简单的设计。

答案 1 :(得分:0)

如果我正确理解你的问题,这应该没问题:

CREATE TABLE IF NOT EXISTS `accounts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `accounts_groups` (
  `account_id` int(11) NOT NULL,
  `group_id` int(11) NOT NULL,
  `start_date` date NOT NULL,
  `end_date` date DEFAULT NULL,
  UNIQUE KEY `account_group` (`account_id`,`group_id`,`start_date`),
  KEY `group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE IF NOT EXISTS `account_balances` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account_id` int(11) NOT NULL,
  `date` date NOT NULL,
  `balance` decimal(11,2) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

ALTER TABLE `accounts_groups`
  ADD CONSTRAINT `accounts_groups_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`),
  ADD CONSTRAINT `accounts_groups_ibfk_2` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`);

ALTER TABLE `account_balances`
  ADD CONSTRAINT `account_balances_ibfk_1` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`);