Php 通过mysql使用存储过程进行社交排名
我正在为数据库中的项目开发一个社会排名引擎。我想我已经解决了逻辑问题(在我的头脑中),现在正在进行实现。我希望要么是“好吧,这看起来是对的”,要么是如果我完全走错了方向,“你的白痴,卸载”。以适用者为准 基本上,我有几个表设置如下(非常简化,[…]表示未显示的其他列) 现在,目标是当用户登录并对特定项目进行“投票”时,它会在投票表中添加一行,但也会使用(我假设)一个基于类似于其他社交排名网站(如reddit的“热门”和“顶级”排序算法)的算法的存储过程在后台自动更新项目排名 我自己对该问题的假设/解决方案是执行以下操作:Php 通过mysql使用存储过程进行社交排名,php,mysql,database,database-design,stored-procedures,Php,Mysql,Database,Database Design,Stored Procedures,我正在为数据库中的项目开发一个社会排名引擎。我想我已经解决了逻辑问题(在我的头脑中),现在正在进行实现。我希望要么是“好吧,这看起来是对的”,要么是如果我完全走错了方向,“你的白痴,卸载”。以适用者为准 基本上,我有几个表设置如下(非常简化,[…]表示未显示的其他列) 现在,目标是当用户登录并对特定项目进行“投票”时,它会在投票表中添加一行,但也会使用(我假设)一个基于类似于其他社交排名网站(如reddit的“热门”和“顶级”排序算法)的算法的存储过程在后台自动更新项目排名 我自己对该问题的假设
DELIMITER //
DROP PROCEDURE IF EXISTS updateRank//
CREATE PROCEDURE updateRank(IN itemId INT())
COMMENT 'Generates a new rank and updates the Items table'
BEGIN
DECLARE vote_sum,published_date INT DEFAULT 0;
SELECT COUNT(id) INTO vote_sum,
FROM Votes
WHERE item_id = itemId;
SELECT date INTO published_date
FROM Items
WHERE id = itemId;
SET @o = log(max(abs(vote_sum), 1), 10);
SET @ts = published_date - 1307557809;
SET @r = round(@0 + 1 * @ts / 45000, 7);
UPDATE Items
SET rank = @r
WHERE id = itemId;
END;
//
delimiter ;
INSERT INTO Votes (user_id,item_id) values (:userid,:itemid ) CALL updateRank(:itemid);
然后,在我的PDO查询中添加以下内容:
DELIMITER //
DROP PROCEDURE IF EXISTS updateRank//
CREATE PROCEDURE updateRank(IN itemId INT())
COMMENT 'Generates a new rank and updates the Items table'
BEGIN
DECLARE vote_sum,published_date INT DEFAULT 0;
SELECT COUNT(id) INTO vote_sum,
FROM Votes
WHERE item_id = itemId;
SELECT date INTO published_date
FROM Items
WHERE id = itemId;
SET @o = log(max(abs(vote_sum), 1), 10);
SET @ts = published_date - 1307557809;
SET @r = round(@0 + 1 * @ts / 45000, 7);
UPDATE Items
SET rank = @r
WHERE id = itemId;
END;
//
delimiter ;
INSERT INTO Votes (user_id,item_id) values (:userid,:itemid ) CALL updateRank(:itemid);
如果这看起来很迟钝的话,那是因为我对存储过程(最好)相当生疏,而对noob(最坏)完全不了解
我的问题基本上是:有没有更好的方法?我的妻子出去吃午饭了吗?这可以在幕后完成吗(即,不在我的查询中调用过程)?我应该使用InnoDB或MyISAM作为我的主要引擎吗?我有理由想在这个特定的项目中使用InnoDB(至少有几个表),但是我读到的所有东西似乎都告诉我永远不要使用InnoDB。。。弊大于利
编辑
建议更换
SELECT COUNT(id) INTO vote_sum
FROM Votes
WHERE item_id = itemId;
有以下几点
SELECT vote_count INTO vote_sum
FROM Votes
WHERE item_id = itemId;
这更有意义吗?然后增加投票计数字段,而不是简单地更新分数?不知道您是否知道,但有一种更简单的方法 只需将分数和VoteCount添加到项目实体
new vote:
Score = (Score*VoteCount+NewVote) / (VoteCount + 1)
VoteCount++;
您不知道哪些用户对哪些项目进行了投票,但
可以将其添加为自己的实体
这对你的mysql来说是一个轻松的工作,因为不算
//编辑
items:
ItemID
...
VoteSum
VoteCount
VoteAvg (computed field, Sum/Count, index to sort fast for "five-stars")
Track of votes - to avoid double-votes and let user delete their vote.
votes:
UserID (PK)
ItemID (PK)
Rating
表决时:
insert into votes(...
update item set VoceCount=VotCount+1,VoteSum=VoteSum+X
问候,
//t没有必要在问题标题中包含[伪标记]。我们这里有真正的标签!好的:(我会羞愧地低下头。嗯……所以本质上,当有人“投票”时,增加VoteCount列,如果有人“未投票”或删除了他们的投票,则减少该列?即:在“项目”表中添加一个名为“投票计数”的新列。并将“选择计数(id)”替换为“从中选择投票计数…”在我的程序的第一部分?是和否。不可能删除投票wo,因为平均值是存储的全部。请参阅更新。