在sql中链接继承

时间:2017-03-22 15:36:51

标签: php sql mysqli database-design architecture

我正在尝试在我的应用程序架构中创建一个链式继承情况。我希望有各种位置分组,从一个国家一样大到一个小到一个地址,国家/地区&gt;州&gt;城市&gt;地址,以及任意分组,如“蓝色组”和“贵宾位置”。< / p>

您可以看到我刚刚用来表示可能实体的示例表 example table of data that I whipped up

纽约美国东北部的纽约百老汇大道从美国曾祖父母的位置继承了它的“#8b0000”颜色,但是会使用它自己的“macys.png”封面照片。英国哥伦比亚会从加拿大的母公司位置获得它的颜色和照片。等

一般来说,我的目标是:

  • 每个位置都可以拥有自己的数据或空值。
  • 继承特征(例如巴黎可以从法国继承它的颜色,如果没有它自己的话)。
  • 用户可以创建的任意分组(“蓝色组”,“表现不佳者”)

这只是我的第一次通过方法。

SQL是否适合这种继承?例如,似乎不太可能以这种链式继承方式从与sql相同的表中的祖先非常容易地select数据。

有什么比这更好的方法呢?

1 个答案:

答案 0 :(得分:1)

看起来我们所拥有的是分层数据。最能代表树的数据。

enter image description here

此类数据的最佳选择是XML或JSON。但是,有很多方法可以在SQL中表示这种类型的数据。 DB Architect Bill Karwin -Author SQL Antipatterns-详细讨论了它们here。选择最适合你的。

enter image description here

您当前的表格设计是adjacency list。它可以使用,但有一些警告。首先,它无法处理任意数量的级别。这意味着您必须提前知道 - 您将支持的最高级别。从你的例子看,这看起来像五个。美国在顶部。百老汇大道在底部。

查询五层邻接列表将是5X自联接,就像这样。

SELECT 
    t1.name AS Lev1Name, 
    t2.name as Lev2Name, 
    t3.name as Lev3Name, 
    t4.name as Lev4Name, 
    t5.name as Lev5Name,
    COALESCE(t5.name,t4.name,t3.name,t2.name,t1.name) AS InheritedName,
    COALESCE(t5.color,t4.color,t3.color,t2.color,t1.color) AS InheritedColor
FROM MyTable AS t1
LEFT JOIN MyTable AS t2 ON t2.parent_location_id = t1.id
LEFT JOIN MyTable AS t3 ON t3.parent_location_id = t2.id
LEFT JOIN MyTable AS t4 ON t4.parent_location_id = t3.id
LEFT JOIN MyTable AS t5 ON t5.parent_location_id = t4.id
WHERE t1.name = 'USA'

这有效,但是哎哟。它不是最优雅的。它仍然可以满足您的需求。 更新:添加了一些COALESCE列,以便您可以看到“继承”值。根据用户的需要,您可能希望将该表从邻接列表重新设计为其他选项之一。看看Mike Hillyer关于如何将邻接列表转换为嵌套集的精彩文章here

祝你的设计好运!