我只是在学习规范化,所以如果这是一个愚蠢的问题,请原谅我。
我有一张表TBL_Users
,主键为ID
。跟踪我最近想过的朋友是谁做了一个带有两个外键的表,这两个外键都是另一个人的ID。然而,我越是想到这一点,我不禁想到必须有更好的方法。
+----+------+ | ID | Name | +----+------+ | 1 | Al | | 2 | Bob | +----+------+
该模型意味着我必须复制所有信息或两次调用TBL_Friends。
如果表是
,则为IE+----+--------+ | ID | Friend | +----+--------+ | 1 | 2 | | 2 | 1 | +----+--------+
然后我有重复的信息,必须拨两个电话来添加/删除朋友。
另一方面,如果我只是做
+----+-----+ | ID | ID2 | +----+-----+ | 1 | 2 | | 3 | 1 | | 4 | 1 | +----+-----+
情况似乎更糟,因为我必须在任何时候查询数据库两次,无论是收集信息还是添加/删除朋友。
当然,我可以忽略一个更简单的解决方案吗?
答案 0 :(得分:1)
您不需要使用两个查询,只需使用一个带有OR
子句的查询。
SELECT
(CASE WHEN
WHEN id1 = XXX THEN id2
ELSE id1
END) AS friend_id
WHERE
id1 = XXX OR id2 = XXX
XXX
是您正在查找的用户的ID。
这符合您提供的简单案例。
如果您的模型变得更加复杂,我们可以像您的第一个解决方案一样查看表格的其他解决方案和/或非规范化。
答案 1 :(得分:1)
您需要回答的问题是:以下两个陈述是否相同?
这取决于背景。在社交网站中,Al和Bob只是图表上的节点,只要它们之间存在足够的链接即可。
但如果Al跟踪Bob,那么Al可能会根据自己的喜好断言#1,Bob永远不会同意声明#2。或者考虑一个类似的政治家:
这两种陈述同时是真实的,但这里有一些复杂的管理结构,这种情况并不常见。
在这两种情况下,您的第一个表不包含重复数据,因为(1,2)与(2,1)不同。如果你确实选择第二个解决方案,你应该执行一个规则,如果(1,2)存在,(2,1)就不存在。
在某些情况下,您的第一个解决方案是合适的解决方案,而第二个解决方案是正确的解决方案。换句话说,数据建模很难:)
关键是,首先让你的逻辑模型正确。在编写查询之前忘掉SQL。如果您的表设计正确,SQL将会流动。或者换句话说,如果您发现难以编写查询,则可能是您的数据模型错误。