我有對稱用戶關係的表,從表中選擇:有效的方法,其中條件1或反轉條件1
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可以是在任一兩列的(見在用戶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
性能問題通常最終成爲「基準測試並親自體驗」。因爲你的user_a/user_b列都沒有索引,所以不管解決方案如何,你最終都會進行全表掃描。 – 2013-03-04 18:34:49
@MarcB我遵照你的建議,實施了benchark。獲獎者是方法2) – Alex 2013-03-04 18:51:55
怎麼樣'SELECT * 從那裏(USER_A =朋友 :USER_A OR USER_A =:USER_B) AND(USER_B =:USER_A OR USER_B =:USER_B) LIMIT 1;' – SparKot 2013-03-04 19:05:39