如何解决“表名加入表”?

时间:2014-07-23 07:38:26

标签: mysql sql database-design

我偶然发现了一个数据库设计,其中一个表在一列中包含需要连接的表的名称,在另一列中包含该表的外键(整数,而不是外键名称)。

我想知道你会如何解决这个问题?

这是目前的情况:

表聊天:

id   |   someColumn   |   chatter_id   |   chatter_ref
--------------------------------------------------------
1        2                1                customers
2        3                1                colleagues
3        4                2                customers

表客户:

id   |   colA
-------------
1        whatever
2        hello_world

表同事:

id   |   colB
-------------
1        yesyes

编辑:

我要做的是,有多个chatting表,每个引用表一个。

像这样:

表chat_customers(使用customers表的外键):

id   |   someColumn   |   chatter_id
------------------------------------
1        2                1         
3        4                2         

表chat_colleagues(使用同事表的外键):

id   |   someColumn   |   chatter_id 
------------------------------------
2        3                1         

我会select case when chatter_ref = 'customers' then customers.colA else colleagues.colB end from ...多个查询,而不是连接所有表并根据列chatter_ref(使用union来决定从哪个表中选择)。这是要走的路吗?有没有更好的方法规范化这个?

3 个答案:

答案 0 :(得分:2)

这是经典的Polymorphic Association反模式。有许多可能的解决方案:

1个专属弧(如Argeman所建议的),例如对于聊天桌

id | someColumn | customerId | colleagueId
------------------------------------------
1    2            1
2    3                         1
3    4            2

其中customerId和colleagueID都可以为空,并且其中一个必须不为null。可以在customerId和colleagueId上声明外键。

2反转关系,例如从聊天表中删除chatterId和chatterRef并创建两个新表

客户聊天

chattingId | customerId
-----------------------
1            1
3            2

同事聊天

chattingId | colleagueId
------------------------
2            1

可以在customerId和colleagueId上声明外键。

3为客户/同事(如人员)创建超类型表,并让聊天表引用此新表的主键。

答案 1 :(得分:1)

我会在聊天表中放入两个或更多可空行,这些行引用不同的其他表。

例如,一列chatter_colleague和一个chatter_customer。这也不是很好,但我不知道任何真正的好解决方案!

这需要一些努力来保持桌面清洁,但据我所知,否则提供最佳的连接和索引功能。这很简单,这在我看来是可取的。

答案 2 :(得分:0)

将引用表的行合并为一个“表”并包含源表的名称(作为文字值),以便您可以将它们彼此区分开来,然后将主表连接到该表,同时加入id和源名称:

select
    c.id,
    c.someColumn,
    d.data
from chatting c
left join (
    select 'customers' type, id, colA data from customers
    union all
    select 'colleagues', id, colB from colleagues) d
  on d.type = c.chatter_ref
  and d.id = c.chatter_id