対称的なユーザー関係のテーブルがあります:
CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_a` int(11) NOT NULL DEFAULT '0',
`user_b` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
この表には次の情報が含まれています。
- IDが1のユーザーはIDが2のユーザーの友達です
- IDが3のユーザーはIDが1のユーザーの友達です
は、次のように結論付けています。
- ID 1 のユーザーには 2 人の友達 (ID 3 と ID 2) がいます
- ユーザーの ID は 2 つの列のいずれかになります(ユーザー ID 1 を参照)。
ユーザー 1 がユーザー 3 と友達であるかどうかを確認する効率的なクエリを作成するにはどうすればよいですか?
なぜ私は効率的な方法について尋ねているのですか?まあ、私には 3 つの異なるソリューションがあるため (さらに多くのソリューションがある可能性があります)、それらすべての中で最も効率的なものを選択するのに苦労しています。何か助けはありますか?
アプローチ 1:
SELECT user_b AS user_a
FROM friends
WHERE (user_a = :user_a AND user_b = :user_b)
UNION ALL
SELECT user_a
FROM friends
WHERE (user_b = :user_b AND user_a = :user_a)
アプローチ 2:
SELECT * FROM friends WHERE (user_a = :user_a AND user_b = :user_b) OR
(user_b = :user_a AND user_a = :user_b)
アプローチ 3:
SELECT user_a FROM (
SELECT user_b AS user_a
FROM friends
WHERE user_a = :user_a
UNION ALL
SELECT user_a
FROM friends
WHERE user_b = :user_a
) AS newtab WHERE newtab.user_a = :user_b;
PHP チェック:
$my_id = 1;
$friend_id = 3;
$stmt = $dbh->prepare("SELECT ..."); // approach 1 or 2 or 3 or ...
$stmt->bindParam(':user_a', $my_id, PDO::PARAM_STR);
$stmt->bindParam(':user_b', $friend_id, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0) {
echo "You are friends";}
else { echo "he is not your friend";}
パフォーマンスに関して - どちらのアプローチが優れていますか?
編集:
テスト:
$start_2 = microtime(true);
for ($i = 1; $i <= 100; $i++) {
$stmt->execute();
}
$end_2 = microtime(true);
結果:
1 : 0.14095306396484
2 : 0.063449859619141
3 : 0.18946194648743