二重の関係を保存するエレガントな方法はありますか(つまり、ユーザー1とユーザー2が友達です)
-
26-10-2019 - |
質問
今月は2つの異なる作業で同じ問題に遭遇しました。
Version 1: User 1 & User 2 are friends
Version 2: Axis 1 & Axis 2 when graphed should have the quadrants colored...
問題は、RDBMSを使用してこの情報を保存して照会するためにエレガントな方法を見ないことです。
2つの明らかなアプローチがあります。
アプローチ1:
store the information twice (i.e. two db rows rows per relationship):
u1, u2, true
u2, u1, true
u..n, u..i, true
u..i, u..n, true
have rules to always look for the inverse on updates:
on read, no management needed
on create, create inverse
on delete, delete inverse
on update, update inverse
Advantage: management logic is always the same.
Disadvantage: possibility of race conditions, extra storage (which is admittedly cheap, but feels wrong)
アプローチ2:
store the information once (i.e. one db row per relationship)
u1, u2, true
u..n, u..i, true
have rules to check for corollaries:
on read, if u1, u2 fails, check for u2, u1
on create u1, u2: check for u2, u1, if it doesn't exist, create u1, u2
on delete, no management needed
on update, optionally redo same check as create
Advantage: Only store once
Disadvantage: Management requires different set of cleanup depending on the operation
f(x、y)を使用してf(x、y)を使用してキーの線に沿って進む3番目のアプローチがあるのではないかと思います。 f(y、x) "
私の腸は、これらの要件を満たすことができるビットワイズ操作の組み合わせがあるべきだと言っています。 2列のようなもの:
key1 = x && y key2 = x + y
数学部門でより多くの時間を費やし、社会学部門で時間を短縮した人々が、これの可能性または不可能性の証拠を見て、迅速な「[You Moron、]その簡単に証明された(IM)を提供できることを望んでいます。可能、このリンクを参照してください」(名前を呼び出すオプション)
他のエレガントなアプローチも大歓迎です。
ありがとう
解決
また、追加の制約を追加することにより、2番目のアプローチを使用する方法もあります。それを確認します u1 < u2
:
CREATE TABLE User
( Name VARCHAR(10) NOT NULL
, PRIMARY KEY (Name)
) ;
CREATE TABLE MutualFriendship
( u1 VARCHAR(10) NOT NULL
, u2 VARCHAR(10) NOT NULL
, PRIMARY KEY (u1, u2)
, FOREIGN KEY (u1)
REFERENCES User(Name)
, FOREIGN KEY (u2)
REFERENCES User(Name)
, CHECK (u1 < u2)
) ;
読み取り、作成、挿入、または更新するルールは、 (LEAST(u1,u2), GREATEST(u1,u2))
.
他のヒント
SQLでは、最初のアプローチをサポートするための制約を簡単に実装できます。
CREATE TABLE MutualFriendship
(u1 VARCHAR(10) NOT NULL,
u2 VARCHAR(10) NOT NULL,
PRIMARY KEY (u1,u2),
FOREIGN KEY (u2,u1) REFERENCES MutualFriendship (u1,u2));
INSERT INTO MutualFriendship VALUES
('Alice','Bob'),
('Bob','Alice');
興味のある人のために、私はいくつかのビットワイズ操作で遊んでいたが、以下がf(x、y)の基準を満たしているように見えることを発見した。
#Python, returns 3 tuple
def get_hash(x, y):
return (x & y, x | y, x * y)
しかし、私はそれを証明することはできません。
「xはyの友達です」。
(x、y)ペアのテーブルを定義し、標準形式を実施します。たとえば
Friends Unionの選択x、yを選択してxを選択します。
ベーステーブルに対する更新(欠点:アップデーターは、実施された標準形式に注意する必要があります)、ビューに対してクエリを実行します。
友達の数を1に制限しているようです。これが当てはまる場合は、U1、U2 U2、U1 U3、Null U4、U5 U5、U4などを使用します。
U3には友達がいません。