如果表中存在对称关系,如何以优雅的方式表示它?
例如,有一个名为Friend
的表,其中应包含两个用户的用户ID。如果我们在此表中使用UID1
和UID2
,当我们想知道A_uid和B_uid是否为朋友时,我们应该使用
SELECT * FROM Friend WHERE (UID1 = A_uid AND UID2 = B_uid) OR (UID1 = B_uid AND UID2 = A_uid);
因为UID1
和UID2
在表示友谊方面是相同的。 在这个困境中最重要的是UID1
和UID2
是对称的。
我认为这很难看,想知道是否有更好的方法。
谢谢!
答案 0 :(得分:5)
我的头脑中的一个想法:如果你的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
约束,我只是认为防止您不小心插入同一个关系会很方便。