7

我有一个带有 SQL Server 后端的 asp.net-mvc 网站。我正在简化我的情况以突出和隔离问题。我在数据库中有 3 个表

  1. 文章表(id、名称、内容)
  2. 位置表(id,名称)
  3. ArticleLocation 表(id​​、文章 ID、位置 ID)

在我的网站上,当您创建一篇文章时,您可以从多选列表框中选择您希望将该文章发送到的位置。

大约有 25 个位置,所以我正在讨论添加一个名为“全局”的新位置作为快捷方式,而不是让人们从列表框中选择 25 个不同的项目。我仍然可以将其作为前端的捷径,但现在我正在讨论是否有利于将其流向后端。

因此,如果我有一篇全球性的文章,而不是在 ArticleLocation 表中有 25 条记录,我将只有一条,然后我会在前端做一些技巧来选择所有项目。我试图弄清楚这是否是一个非常糟糕的主意。

我能想到的事情让我感到紧张:

  1. 如果我创建一篇文章并选择全局但在未来最后添加 3 个新位置怎么办。如果没有这个全局设置,这 3 个位置将无法获取文章,但以新的方式,它们会。我不确定什么更好,因为第二件事实际上可能是您想要的,但它不太明确。

  2. 我对报告有要求,我想按所有全球文章进行过滤。想象一下,我需要一个 article.IsGlobal() 方法。现在我想我可以说如果一个项目的位置数与位置表中的所有记录相同,我可以将其翻译为被认为是全球性的,但由于人们可以添加新位置,我觉得这种方法有点不稳定.

有没有人对在真正反映“所有记录”的参考数据表中创建记录这一困境有任何建议。感谢任何建议

4

6 回答 6

9

应要求,这是我的评论提升为答案。这也是一个扩展它的机会。

我将把我的答案限制在具有单个位置列表的系统上。我已经完成了公司层次结构的事情:公司、部门、地区、州、县、办公室和员工等等。它变得丑陋。

就 OP 的问题而言,似乎AllLocations在表格中添加一点可以Articles明确意图。标记设置为 1 的任何文章都会出现​​在所有位置,无论它们是何时创建的,并且不需要在ArticleLocation表中包含任何条目。如果作者不希望文章自动出现在未来的位置,则仍然可以将文章显式添加到所有现有位置。

实施涉及更多的工作。我会在and表中添加INSERTUPDATE触发器,以强制执行以下规则:位已设置且 中没有相应的行,或者位已清除且可显式设置位置。(个人偏好让数据库在可行的情况下保护自己免受“坏数据”的影响。)ArticleArticleLocationAllLocationsArticleLocation

根据您的需要,表值函数是隐藏一些脏工作的好方法,例如dbo.GetArticleIdsForLocation( LocationId )可以在AllLocations内部处理标志。您可以在存储过程和临时查询中使用JOINArticle。在其他情况下,视图可能是合适的。

欢迎您借用的另一个功能(“从您的朋友那里窃取!”)是让管理员的登录页面成为“例外”页面。在这个地方,我展示了从大规模的燃烧灾难到单纯的小错误。在这种情况下,与零位置相关联的文章将被视为非关键的,但值得检查。

添加新位置的人可能会对在每个位置明确显示的文章感兴趣,所以我可能会有一个网页。可能应该更新某些文章以明确说明新位置或重新考虑将其更改为所有位置。

于 2013-06-07T02:08:26.550 回答
6

这是一个好主意……代表“所有其他记录”吗?

在表格中表示一棵树是个好主意吗?树的根代表“所有其他记录”。

树和层次结构并不容易使用,但是有很多例子、文章和书籍可以解决这个问题——比如 Celko 的Trees and Hierarchies in SQL;Karwin 的SQL 反模式

所以你在这里实际上拥有的是一个层次结构(也许只是一棵树)——它可能有助于从一开始就以这种方式解决问题。您的示例中的 theGlobal只是另一个Location(树的根),因此当添加新位置时,您可以决定它是否是 the 的子节点Global


事实

  • 位置(LocationID) 存在。
  • 位置(LocationID) 包含在父位置(LocationID) 中。
  • 文章(ArticleID) 存在。
  • 文章(ArticleID) 在位置(LocationID) 可用。

约束

  • Each Location包含在at most one Parent Location中。It is possible that for some 父位置more than one 位置包含在that 父位置中。

  • It is possible that some 文章more than one Location and that for some 位置可用,more than one 文章在that Location可用。


逻辑的

在此处输入图像描述


这样,您可以将任何位置分配给文章——但必须在需要时将其解析为叶级别

层次结构(树)在这里以“幼稚的方式”表示;改用闭包表、嵌套集或枚举路径——或者,如果你喜欢递归......

于 2013-06-06T12:04:21.957 回答
2

tl;博士

在这种情况下,据我了解,我认为在 Location 表中创建一个“全局”位置是个好主意。我绝对发现在文章表中创建一个“全局”标志更可取。


“这是个好主意吗……?” 不是我们喜欢在 SO 上回答的问题。这主要是一个辩论问题,而不是问答问题,此外,我们的社区有足够的创造力来提出一些例子,无论如何“它”都是一个好主意。

对于您更具体的问题,我如何在数据库中表示“所有位置”?这是基于您的业务需求的判断。

您是否希望“所有位置”包括未来的位置?

如果不是,那么您可能只应该将“所有位置”实现为选择数据库中所有当前位置的助手。

您是否预计会有位置层次结构?

现实世界的位置具有显着的层次结构:

  • 全球的
  • 跨国(大陆、贸易区)
  • 国家
  • 行政区域(州、省、州等)
  • 城市
  • 邻里

如果您认为您想要选择一个国家,而不是全球,那么实施像 Damir 建议的分层表示是最好的方法。但是,如果您不确定除了 Global 之外是否还会有任何其他位置分组,那么现在分层数据结构的工作量太大了。您需要做的就是确保您当前的实现具有到可能的未来分层表示的迁移路径。

全局作为伪位置

如果您确实希望将未来位置包含在 Global 中并且不需要分层位置结构,那么根据多年的经验,我的直觉是将“Global”创建为伪位置。也就是说,Global 将是 Location 表中的位置之一,但它具有特殊含义。这绝对是一种权衡,但好处是改变数据结构以支持 Global,这意味着“Global”创建的所有特殊情况都是通过在查询中排除或包含某些位置而不是通过检查某处的某些标志来处理的. (或者,如果您喜欢标志,您可以在 Location 表中添加一个“伪位置”标志。)

使用 Global 作为位置,会自动处理对 Location 表的添加或删除。对所有全球文章的查询很简单:与对任何其他位置的所有文章的查询相同。按位置报告文章也很简单,全球文章与任何其他位置一样出现在报告中。您还可以表示“全球”文章(所有当前和未来位置)和“所有位置”文章(所有当前位置但没有未来位置)之间的差异。

选择应该在特定位置可见的所有文章稍微困难一些,现在它是对“全局”以及该位置的检查,但至少它是检查同一个表中的 2 个值而不是检查两个不同的表。

SELECT article_id FROM ArticleLocation WHERE location_id in (1, 5);

对比

SELECT article_id FROM ArticleLocation WHERE location_id = 5
UNION
SELECT id FROM Article WHERE is_global;
于 2013-06-06T17:13:33.853 回答
1

从逻辑上看,正如您所描述的,GLOBAL 实际上应该是全球性的并且保持全球性,即使您添加了新位置(问题 1 已解决)。但这也意味着 GLOBAL 与“所有位置”不同(因为可能还存在一些我们尚未定义的其他位置)。我认为您的要求 2 尤其需要这种逻辑 - 否则添加新位置将完全失败。

分析完毕!从上面我们看到 GLOBAL 比所有这些位置都重要。尝试将其定义为位置是没有意义的。寻求最简单的解决方案!

  • 文章表(id、name、content、global

即布尔标志 - 文章是否是全局的。在 UI 中,只需将其用作复选框- 如果选中,多选框将被禁用。简单,容易,满足要求。完毕!

于 2013-06-11T01:52:08.677 回答
0

我同意@HABO 的评论(他应该已经发布了——如果他这样做了,请支持他)。为表格文章添加一个属性以识别与所有位置相关联的项目,现在未来,大概在文章的生命周期内,从长远来看应该可以节省您的时间和精力。当然,触发器和计数都可以解决问题,但是它们很尴尬,并且如果/当后续系统更改发生时支持它们会很痛苦。UI 使用起来会更简单,因为用户只需单击一个复选框(或其他任何内容),而不是在不可预见长度的下拉列表中多次单击所有内容。

(@Damir 的层次结构想法也可以,但是——从经验丰富的经验来看——它们很麻烦,除非有更多的系统和/或业务用途,否则我不会在这里介绍一个摆脱它。)

于 2013-06-06T15:25:09.497 回答
0

添加新位置时是否需要自动将一些文章添加到新位置?如果是,那么在这种情况下,我会考虑在后端添加新的“全局”属性。

否则可能不值得努力。即使您为每篇文章选择了 10000 篇文章和 20 个不同的位置,这将是大约 20 万条记录,这在您设置索引时还不错。

检查您现有的数据,看看人们是如何选择位置的。如果大多数用户只选择几个位置而不是全部,那么它确实是一个边缘案例,除非它真的产生问题,否则你不应该处理它。

于 2013-06-03T08:35:26.397 回答