请帮助,以有效的方式强制限制用户标记为收藏的图书数量。
user_book 表
bookID | userID | Attr | addedTime <- with index UNIQUE(bookID,userID)
Attr
列包含用户在书上设置的属性的位标志。例如:
1
(二进制001
)如果用户拥有该书,2
(二进制010
),如果用户阅读,4
(二进制100
)如果用户将其标记为收藏所以Attr=6
表示用户不拥有该书,但她阅读并将其标记为收藏
当用户尝试在现有记录上设置favorite
标志或添加设置了该标志的新记录时,我想强制实施25个收藏夹限制。如果已经达到限制,我想从最旧的收藏记录中删除该标志。我目前的实施似乎过于复杂:
假设用户25
想要将图书100
设为收藏,我会这样做(伪代码)
//sql to get all books the user has marked as favorite; oldest book first
SELECT bookID from user_book WHERE userID=25 AND (Attr & 4)>0
ORDER BY addedTime ASC
if(($count = count($results)) > 24){ //if more than 24 books are favorited
$bookIDsToUnset = array_slice($results,0,$count-24); //get books over limit
$bookIDsToUnset = implode(',' , $bookIDsToUnset);
//unset the favorite attribute from the books over the limit
UPDATE user_book SET Attr = Attr^4 WHERE userID=25
AND bookID IN ($bookIDsToUnset)
}
//make bookID 100 a favorite
UPDATE user_book SET Attr = Attr | 4 WHERE userID=25 AND bookID=100
这需要最多3个数据库查询,因此效率低下。任何人都可以提出更好的选择吗?
答案 0 :(得分:2)
您可以在一个查询中取消设置收藏夹:
update user_book ub join
(select ub2.*
from user_book ub2
where ub2.userId = 25 and (attr & 4) > 0
order by ub2.addedTime desc
offset 24 limit 999
) keep24
on ub.bookid = keep24.bookid and ub.userid = keep24.userid
set attr = attr ^ 4;
使用user_book(userId, addTime)
和user_book(userId, bookId)
的索引,这应该非常快。
然后,您可以使用insert
声明插入新收藏夹。
注意:我不认为自动删除收藏夹是个好主意,但这似乎是您的应用程序设计。