我有一个PostgreSQL数据库,其中包含各种教育数据,如学校级别的考试成绩和入学人数。我需要将注册与测试分数分开,因为数据是在不同的谷物上。即使注册与测试分数数据的粒度不同,但许多维度都是相同的。例如,我有:
~ ---------------------------------------------------------------------------------~
| Test Scores Fact |
|-------------|-----------|----------|-----------|--------------|------------|-----|
| school_code | test_code | grade_id | gender_id | ethnicity_id | subject_id | ... |
|-------------|-----------|----------|-----------|--------------|------------|-----|
~ --------------------------------------------------------~
| Enrollment Fact |
|-------------|----------|-----------|--------------|-----|
| school_code | grade_id | gender_id | ethnicity_id | ... |
|-------------|----------|-----------|--------------|-----|
这种结构在后端很好,但在Qlikview中,这会创建一个合成密钥。合成密钥的解决方案似乎通常是通过Qlikview脚本来替换它的链接表,这也是我的方法。但这似乎没有扩展,因为当我添加第三个事实表(在另一个粒子上)包含更多相同的维度时,如果我创建另一个链接表,现在我的两个链接表开始关联,因为它们通常包含几个命名字段,Qlikview的回应是创建更多的合成密钥?
我对Qlikview比较陌生,我自己也在工作。如何处理具有共同尺寸的不同颗粒的多个事实?
编辑:
我已经为这个问题提供了解决方案,这个问题已经在生产环境中工作了不到一年!请参阅下面的答案......
答案 0 :(得分:7)
看到这个问题的受欢迎程度,我将添加我的实际解决方案,以便人们有一个工作的例子,由于某种原因很难找到这样一个常见的问题...
我继续创建链接表。这个解决方案至今仍然像一个黑客,因为它创建了一个巨大的表,其中包含所有事实表中每个键的笛卡尔积...但它确实有效。
问题:您的数据库中有多个事实表;几乎每个数据库都出现过一次。这些事实表中的一些(或全部)共享相同的关键字段;没问题,对吧?错误。不幸的是,由于Qlik的关联性质,而不是每个事实表都很好地链接到他们的查找表,你的事实表现在彼此关联并对你的数据模型造成严重破坏;创建循环引用和无数量的合成键。
解决方案:创建链接表。听起来很简单吧?嗯,确实如此,但如果没有初步解释,它也很难记录并且难以理解。您可能想知道......什么是链接表?它是所有事实表中所有键的笛卡尔积。这如何解决问题?它会删除事实表之间的所有不需要的关联,因为每个事件表现在只包含一个唯一的连接键。这些唯一键仅与链接表关联,其中包含所有唯一的连接键以及所有单独的键。随后链接表将与您的查找表相关联,并且一切都会很好。
<强>实施强>
此实现将使用上述问题中包含的两个表; test_scores_fact
和enrollment_fact
。
test_scores_fact | enrollment_fact | school | gender | ...
---------------- | --------------- | ------ | ------ | ---
school_code (FK) | school_code (FK) | school_code (PK) | gender_id (PK) |
test_code (FK) | grade_id (FK) | school_name (FK) | gender_desc |
grade_id (FK) | ethnicity_id (FK) | address | ... |
gender_id (FK) | gender_id (FK) | ... |
ethnicity_id (FK) | number_enrolled (F) |
subject_id (FK) |
test_score (F) |
FK = Foreign Key
PK = Primary Key
F = Fact
如您所见,这两个事实表具有重叠的键school_code
,grade_id
,gender_id
和ethnicity_id
。在关系模型中,每个关键字段都有一个对应的表,其中包含有关密钥的其他信息。由于Qlikview根据字段的名称关联表格,因此该模型不符合Qlikview的关联性质;即使你不想要它。您确实希望命名字段与其查找表关联,但是您不希望事实表中的命名字段与关联。不幸的是你无法阻止这种行为。您必须实现链接表...
在Qlikview脚本中,创建一个临时事实表,该表加载到数据库表的所有字段中:
[temp_test_scores]:
LOAD school_code,
test_code,
grade_id,
gender_id,
ethnicity_id,
subject_id,
test_score;
SQL SELECT * FROM <database connection>
连接密钥并删除所有单独的密钥:
[test_scores]:
LOAD school_code & '_' test_code & '_' grade_id & '_' gender_id & '_' ethnicity_id & '_' subject_id as test_key,
test_score
RESIDENT [temp_test_scores];
重复步骤1&amp;每个事实表2:
[temp_enrollment]:
LOAD school_code,
grade_id,
ethnicity_id,
gender_id,
number_enrolled;
SQL SELECT * FROM <database connection>
[enrollment]:
LOAD school_code & '_' & grade_id & '_' & ethnicity_id & '_' & gender_id as enrollment_key,
number_enrolled
RESIDENT [temp_enrollment];
通过将各个密钥连接到一个表中来创建链接表:
[temp_link_table]:
LOAD DISTINCT
school_code,
test_code,
grade_id,
gender_id,
ethnicity_id,
subject_id
RESIDENT [temp_test_scores];
CONCATENATE ([temp_link_table])
LOAD DISTINCT
school_code,
grade_id,
ethnicity_id,
gender_id,
number_enrolled
RESIDENT [temp_enrollment];
/**
* The final Link Table will contain all of the individual keys one time as well as your concatenated keys
*/
[link_table]:
LOAD DISTINCT
school_code,
test_code,
grade_id,
gender_id,
ethnicity_id,
subject_id,
school_code & '_' test_code & '_' grade_id & '_' gender_id & '_' ethnicity_id & '_' subject_id as test_key,
school_code & '_' & grade_id & '_' & ethnicity_id & '_' & gender_id as enrollment_key
RESIDENT [temp_link_table]
删除临时表,使它们不会出现在您的数据模型中:
DROP TABLE [temp_test_scores];
DROP TABLE [temp_enrollment];
DROP TABLE [temp_link_table];
这将删除事实表之间的所有关联,因为它们之间现在不存在公共字段名称。每个事实表将通过创建的连接密钥链接到链接表。然后,链接表将与每个单独的查找表相关联。您的Qlikview数据模型不包含任何合成密钥或循环引用。
如果您将来创建另一个事实表,请按照步骤1&amp;再次2,并将任何新的单个密钥添加到链接表,并将新的连接密钥添加到链接表。它可以轻松扩展。
祝你好运!
答案 1 :(得分:4)
在QlikView中建模数据有两种主要策略来处理多个事实表:
通常将您的事实表附加到一个事实表中 作为QlikView的语法称为CONCATENATED FACT 将数据附加到表是使用CONCATENATE前缀( 相当于SQL UNION操作)
建立一个链接表(到目前为止你做了什么)对于大多数人来说 实现,选项1是适当的方法。 a的属性 连带事实可概括为:
肯定:
否定:
如何构建链接表是一个复杂的主题,但依赖于传统的数据库链接表设计技术。很容易出错并生成链接表,这些表可能在前端产生正确的结果但是过大,消耗内存和CPU资源。
根据我的经验,建模不佳的QlikView数据模型是造成性能不佳的最常见原因。
我希望QlikView中的多事实建模的这一快速,非详尽的介绍可以为您提供一些帮助,并为您提供正确的课程。
答案 2 :(得分:2)
我能想到的两种最快捷的方式:
A)您可以将事实表连接到它们所使用的相应表中。您只需要重命名字段以避免与其他表冲突。
B)您可以重命名公共字段,可以通过
完成QUALIFY
(在加载事实表之前)和UNQUALIFY
(在加载事实表之后)假设事实表具有可以链接到主表的唯一id字段名称,则不必重命名主表中的任何内容
我会选择B-1,因为这似乎不那么麻烦。
QUALIFY
A,
B,
C,
ID;
FactTable1:
Load ID,
A,
B,
C,
From [FactTable1];
FactTable2:
Load ID,
A,
B,
C,
From [FactTable2];
UNQUALIFY
A,
B,
C,
ID;
编辑:如果你想从这些链接表创建一个链接表,你可以将事实表连接到一个表中,你将所有列放入其中(很多列都会有空值,但QlikView很适合空值)。
我通常做的是加载事实表并创建一个id字段(RowNo()或autonumberhash128([唯一id字段名列表]),然后当我将它们加载到链接表中时,我包含该id字段最后,我从事实表中删除了所有公共字段,因此它们只存在于链接表中。
答案 3 :(得分:2)
但是,每个事实表都有“共享”字段的不同子集,因此我无法正确键入事实表。
笛卡尔维度的输入之一是针对主题和测试代码的'N / A'(因为它不在注册表中)
因此,当您按“性别”进行衡量时,“测试分数”与具有有效主题和测试代码的维度记录匹配,并且“注册”与“N / A”主题和测试代码的记录匹配
然后,当你按性别卷起时,每次都能很好地工作。