Luk*_*keK 6 sql join query-optimization teradata
我有一个令人讨厌的SQL查询问题,我很乐意帮助一个优雅的解决方案.我试图避免32个左外连接到同一个表.
数据库是Teradata.
我有一张包含1400万条记录和33列的表格.主键(我们称之为Trans_Id)和32个编码字段(让我们称之为encoded_1 ... encoded_32).像这样的东西:
CREATE SET TABLE BigTable ,NO FALLBACK , NO BEFORE JOURNAL, NO AFTER JOURNAL, CHECKSUM = DEFAULT
(
TRANS_ID VARCHAR(20) CHARACTER SET LATIN NOT CASESPECIFIC,
ENCODED_1 VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
ENCODED_2 VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
ENCODED_3 VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
...
ENCODED_32 VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC )
PRIMARY INDEX ( TRANS_ID );
Run Code Online (Sandbox Code Playgroud)
我还有一个包含编码/解码值的表.假设此表中有100条记录.
CREATE SET TABLE LookupTable ,NO FALLBACK , NO BEFORE JOURNAL, NO AFTER JOURNAL, CHECKSUM = DEFAULT
(
UNIQ_PK { just random numbers }
ENCODED_VAR VARCHAR(10) CHARACTER SET LATIN NOT CASESPECIFIC,
DECODED_DESC VARCHAR(50) CHARACTER SET LATIN NOT CASESPECIFIC)
PRIMARY INDEX ( UNIQ_PK );
Run Code Online (Sandbox Code Playgroud)
我想避免像这样讨厌的连接(我使用省略号而不是显示所有32个外连接):
SELECT
TRANS_ID
, a.ENCODED_1
, b1.DECODED_DESC DECODED_DESC_1
, a.ENCODED_2
, b2.DECODED_DESC DECODED_DESC_2
...
, a.ENCODED_31
, b31.DECODED_DESC DECODED_DESC_31
, a.ENCODED_32
, b32.DECODED_DESC DECODED_DESC_32
FROM BigTable a
LEFT OUTER JOIN LookupTable b1 ON a.ENCODED_1 = b1.ENCODED
LEFT OUTER JOIN LookupTable b2 ON a.ENCODED_2 = b1.ENCODED
...
LEFT OUTER JOIN LookupTable b31 ON a.ENCODED_31 = b31.ENCODED
LEFT OUTER JOIN LookupTable b32 ON a.ENCODED_32 = b32.ENCODED
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激.我有一种感觉外加入14M记录32次不是有效的方法来做到这一点!
如果encoded_1、encoded_2等都被用作同一个表的查找键,听起来它们都是“相同的想法”。但我的第一个想法是,在这种情况下更好的设计是:
big_table (trans_id, var_id, encoded_var)
lookup_table (encoded_var, decoded_desc)
Run Code Online (Sandbox Code Playgroud)
那么查询就变成了:
select trans_id, var_id, encoded_var, decoded_desc
from big_table
join lookup_table on lookup_table.encoded_var=big_table.encoded_var
Run Code Online (Sandbox Code Playgroud)
我不知道这是否是真正的字段名称,或者您只是想省略不相关的细节。您可能会在这里遗漏相关细节。encoded_1 和encoded_2 等有什么区别?如果它们可以互换,则没有理由为它们设置单独的字段。确实,它会带来很多问题。即使存在语义差异,如果它们都使用相同的查找表,则它们也必须来自同一域。
例如,几年前,我开发了一个系统来管理我们组织制作和使用的技术手册。每本手册有 3 名管理员。(负责处理预算和时间表的行政经理,负责跟踪谁需要副本并确保他们获得副本的库存经理,以及负责实际文本的内容经理。)但他们都来自同一份人员名单,通常同一个人会担任多个角色,或者可能针对不同的手册担任不同的角色。因此,我们制作了一个包含 ID、姓名、电子邮件地址等的“人员”表,然后在基本手动记录中我创建了 3 列,每个经理类型对应一列。
这是一个巨大的错误。我应该做的是创建一个单独的表,其中包含手动 id、经理类型 id 和人员 id,然后为 3 种经理类型创建 3 条记录,而不是一条记录中的 3 个字段。
为什么?对于三列,我遇到了您所描述的相同问题,尽管规模较小:我必须从手动表连接到人员表三次。像“鲍勃·史密斯负责哪些书?”这样的查询 需要一个令人惊讶的复杂查询,比如
select ... whatever ...
from manual
join person p1 on p1.person_id=manual.admin_id
join person p2 on p2.person_id=manual.stockmanager_id
join person p3 on p3.person_id=manual.contentmanager_id
where p1.name='Bob Smith'
or p2.name='Bob Smith'
or p3.name='Bob Smith'
Run Code Online (Sandbox Code Playgroud)
如果使用单列,那就很简单了
select ... whatever ...
from manual
join manual_manager on manual_manager.manual_id=manual.manual_id
join person on person.person_id=manual_manager.person_id
where person.name='Bob Smith'"
Run Code Online (Sandbox Code Playgroud)
经过所有的重复,程序员有几次不小心只检查了 2 个字段而不是全部 3 个字段,这并不奇怪。如果有 1 个字段,则不可能出现此错误。对于 3 个字段,如果我们添加第四种类型的管理器,我们将不得不添加另一列,然后更改查看这些字段的每个查询。如果有 1 个字段,我们可能不会。ETC。
对于 3 个字段,我们需要 3 个索引,并且还有其他性能影响。
我怀疑同样的想法也适用于你。
如果您的 32 个字段都是完全可互换的,那么该表只需要一个序列号即可创建唯一的 pk。如果它们之间存在一些差异,那么您可以创建一个代码来区分它们。
| 归档时间: |
|
| 查看次数: |
2283 次 |
| 最近记录: |