5

如果表中存在对称关系,如何优雅地表示呢?例如,有一个名为 的表Friend,其中应包含两个用户的用户 ID。如果我们在这个表中使用UID1and UID2,当我们想知道 A_uid 和 B_uid 是否是朋友时,我们应该使用

SELECT * FROM Friend WHERE (UID1 = A_uid AND UID2 = B_uid) OR (UID1 = B_uid AND UID2 = A_uid);

因为UID1UID2在代表友谊方面是相同的。在这个困境中最重要的UID1UID2对称性。

我认为这很丑陋,想知道是否有更好的方法来处理它。

谢谢!

4

1 回答 1

6

我突然想到了一个想法:如果您的 UID 类型需要完全排序,您可以执行以下操作:

CREATE TABLE friends (
  uid1 uid REFERENCES users,
  uid2 uid REFERENCES users,
  PRIMARY KEY (uid1, uid2),
  CONSTRAINT uid1_above_uid2 CHECK(uid1 < uid2)
);

然后你的查询将不得不把较低的放在第一位。但是您可以使用存储过程来保护它,以确保您这样做:

CREATE FUNCTION friends_with(uid, uid) RETURNS SETOF friends AS $$
  SELECT * FROM friends WHERE uid1 = LESSER($1, $2) AND uid2 = GREATER($1, $2)
$$ LANGUAGE SQL;

当然,这必须转换为您选择的 RDBMS。

现在您的查询如下所示:

SELECT * FROM friends_with(5001, 2393);
SELECT * FROM friends_with(2393, 5001);

他们返回相同的结果。

另一方面,你可以用程序保护它而不把CHECK约束放在那里,我只是认为防止你不小心多次插入同一个关系很方便。

于 2011-08-18T05:36:27.600 回答