0

假设我有一个名为 normalize 的表,其中有一个名为 type 的枚举列

根据行(假设类型是 a、b 或 c),我想根据类型进行 LEFT JOIN。

因此,如果 type = a,则 LEFT JOIN ON 表 a .. 如果 type = B,LEFT JOIN ON 表 b ...等

这可以有效地完成吗?还是应该在应用层完成?

4

4 回答 4

1

是的,您应该能够执行以下操作:

SELECT *
FROM parent
    LEFT JOIN a ON (type = 'a' AND parent.id = a.id)
    LEFT JOIN b ON (type = 'b' AND parent.id = b.id)
    LEFT JOIN c ON (type = 'c' AND parent.id = c.id)

您可能需要也可能不需要索引type,具体取决于实际数据和您的 DBMS 的智能程度(利用应该存在于 PK 下的索引)。无论如何,测量真实的数据量。

于 2012-05-29T16:25:26.753 回答
0

一种常见的方法是将类型存储为 1:1 关系。在这种方法中,没有类型枚举列。ID 出现在 1:1 扩展表中的事实表明了它的类型。

select  *
from    BaseTable b
left join
        Type1Table t1
on      t1.Id = b.Id
left join
        Type1Table t2
on      t2.Id = b.Id

因此,具有inb和int1条目的实体必须是类型 1。具有 inb和 in条目的实体t2属于类型 2。这样,信息只存储一次,并且表会显示“类型 1”但不一致没有匹配的行t1是不可能的。

于 2012-05-29T16:08:42.440 回答
0

问题是,即使您使用SELECT table1.* FROM table1 LEFT OUTER JOIN table2,引擎也会评估连接,即使您甚至不需要显示它们。

所以,在我看来,有两种选择:

  • 第一:假设连接是有效的,使用正确的索引和可接受的 I/O,并使用以下查询:

** 见下文,在它的错误列表中 **

  • 假设进行 n 次连接,n 是不同类型的数量(如果每种类型都有一个表),会产生很多开销,然后在应用层进行 2 个查询:第一个获取类型,然后另一个在 switch例如,case 语句从正确的表中检索数据。

解释计划也可以让你很好地了解你在做什么

询问:

SELECT
    IF(t.type = a, ta.value,
        IF(type = b, tb.value, IF(type = c, tc.value, td.value))
    )
FROM 
    table t
        LEFT JOIN type_a_table ta ON t.type = a AND ...
        LEFT JOIN type_a_table tb ON t.type = b AND ...
        LEFT JOIN type_a_table tc ON t.type = c AND ...
        LEFT JOIN type_a_table td ON t.type = d AND ...
于 2012-05-29T16:19:40.267 回答
0

不确定这是否有帮助,但我可能会使用联合来执行您正在寻找的内容

select * 
from BaseTable b left join TypeTableA a on b.id = a.id
union
select * 
from BaseTable b left join TypeTableB b on b.id = b.id
于 2012-05-29T16:20:12.780 回答