限制具有特定属性的mysql记录数

时间:2016-08-07 03:30:02

标签: php mysql

请帮助,以有效的方式强制限制用户标记为收藏的图书数量。

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个数据库查询,因此效率低下。任何人都可以提出更好的选择吗?

1 个答案:

答案 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声明插入新收藏夹。

注意:我不认为自动删除收藏夹是个好主意,但这似乎是您的应用程序设计。