【问题标题】:Handling a Many-to-Many Dimension when all dimensional values have 100% importance当所有维度值都具有 100% 的重要性时处理多对多维度
【发布时间】:2011-03-31 04:45:04
【问题描述】:

我至少会尽量保持简洁。

假设我们正在跟踪一段时间内的账户余额。所以我们的事实表会有这样的列...

账户余额情况表

  • (FK)帐户ID
  • (FK)日期ID
  • ...
  • 余额
  • ...

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

但问题是……帐户可以属于组——在给定日期的任意数量的组。组只是逻辑抽象,除了报告目的之外没有任何实际意义。位于 0、1 或 17 个组中的帐户不会以任何方式影响其余额。例如,AccountID 1 可能位于 Group 38、76、104 和 159 中。Account 2 可能位于 Group 1(其 Group Description 为“Ungrouped”)中。Account 3 可能位于 17 个组中(真实示例)。

另外,我们的用户完全不懂技术。他们不懂 SQL,也没有使用关系数据库的经验,而且过去他们的所有工作都是在一个复杂的 Excel 解决方案中完成的。现在,我们正在构建一个维度模型,他们可以使用 PowerPivot 进行切片和过滤,尽管这些帐户组威胁要将原本极其简单的星型模式转变为足够复杂的东西,以至于用户会犹豫并返回他们当前的意大利面条解决方案。

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

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

多列法 理论上这可以工作,但是,我们确实有一些属于 17 个组的帐户。同样,这些组实际上只是逻辑组——它们没有任何意义,但业务需要它们用于报告目的。让最终用户从 17 个不同的列中过滤掉组不会很好地提高用户接受度,并且可能会导致用户拒​​绝使用该解决方案(我不怪他们)。

桥牌桌 这个计数有效,但我们确实有 26,000 个不同的组。我不认为这是对用户友好的。

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


更新:为澄清起见,我想这里的每个人都可以联想到一个例子,假设你可以在简历上列出关键字技能。它们都与同一个人有关,但您可以拥有任意数量的技能。这些技能不会影响简历上的任何个人衡量标准——即“C++”并不比“C#”更有价值——你不能将所有简历/技能组合放在事实表中,否则你会结束加倍计数(或远远超过两倍;))。

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

所以现在我们...

账户余额情况表

  • (FK)帐户ID
  • (FK)日期ID
  • ...
  • 余额
  • ...

账户维度

  • (PK)账户ID
  • 帐户名称
  • ...
  • (FK)账户组密钥

帐户组支腿

  • (PK)AccountGroupID
  • (PK)帐户ID)
  • 帐户组名称

【问题讨论】:

  • “帐户可以属于组 - 在给定日期的任意数量的组。” :这是否意味着您还想分组存储有关帐户的历史信息? IE。账户 5 在 3 月 3 日之前属于 A 组和 B 组,在 3 月 3 日之后属于 A 组和 C 组?
  • 这些是真实的组还是只是用于过滤的标签?如果一个账号可以同时属于多个组,那么sum(Balance) group by acc_group没有多大意义,是重复计算?
  • 关于@jing,有一个Type 2 渐变维度,应该由outrigger table 处理好。业务不需要它,但无论如何它都会在那里。关于@Damir,这些确实只是为了过滤,所以如果您将所有组/帐户组合放在事实表中,重复计算是一个问题。
  • 在我看来,雪花是要走的路。尽管很丑,Groups joins GroupAccounts joins Accounts joins 事实表仍然比(畏缩)16 小时的电子表格要快。 GroupAccounts 将是一个无事实依据的事实表,就其价值而言。
  • 26K 组,这是一个有趣的数字——他们如何管理这个?我的猜测是,这是 Excel 解决方案扁平化的几个层次组的某种笛卡尔爆炸的结果。我建议研究这些组,看看是否有可能用几个小维度来表示它们。

标签: sql database-design data-warehouse dimensions


【解决方案1】:

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

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

这绝对是困难的 - 界面和用例必须可行,所以我将从那里开始。也许他们做这个报告的方式会动摇——比如组中的等价类或他们划分帐户空间的某种方式。也许组有一个层次结构或组织,使其更易于管理,并可能为更简单的设计提供信息。

【讨论】:

  • 按帐户和按组 这就是他们当前的解决方案(需要 16 小时加载的 Excel 工作表)的工作方式,以及他们未来需要如何继续过滤(在其他维度中相比之下非常简单)。这些帐户处于一个扁平的层次结构中——组只是为了过滤而完成的,原因是相当随意的(相信我,为此开了两周的许多会议试图消除它们)。现有的解决方案迫使他们复制粘贴公式(我称之为电子手工制作),这是受到谴责的,我不希望他们走同样的路。
  • @Jibba Jones 回顾 Kimball 设计技巧 #50 和尚未发布(但通过电子邮件发送)的设计技巧 #133。 kimballgroup.com/html/designtipsPDF/DesignTips2003/…
【解决方案2】:

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

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`);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多