需要支持以找出对cron作业的查询

时间:2011-12-21 22:28:40

标签: php mysql cron vote

我有一个文章投票系统。文章存储在“故事”表中,所有投票都存储在“投票”表中。 'stories'表中的id等于'votes'表中的item_name(因此每个投票都与item_name的item相关)。

我想这样做,当总票数达到10时,它会更新'故事'表中的'显示'字段为“1”的值。

我正在考虑设置一个每小时运行一次的cron作业,以检查所有显示为0的帖子。如果显示= 0,那么它将总结与该文章相关的投票并设置显示= 1如果投票总和> = 10.我不确定它是否有效,因为它可能占用大量服务器资源,不确定。

那么有人可以建议一个可以完成任务的cron工作吗?

这是我的数据库结构:

故事表

enter image description here


投票表

enter image description here


编辑:

例如来自'stories'表的这一行:

id | 12
st_auth | 作者姓名
st_date | 故事日期
st_title | 故事标题
st_category | 故事类别
st_body | 故事体
显示| 0表示未经批准,1表示已批准

此行与“投票”表格中的这一行相关

id | 83 item_name | 12(文章ID) vote_value | 1 for upvote -1 for downvote ...

3 个答案:

答案 0 :(得分:2)

一些事情:

  1. 为什么在投票表中为列item_name命名,当它实际上是文章表的ID时?我建议在文章表中使它匹配,因为它是一个int(11)和一个var_char(255)。此外,您应该将一个外键约束添加到投票表中,因此如果文章被删除,您不会在投票表中孤立一行。

  2. 为什么vote_value列为int(11)?如果它只能是两个状态(1或-1),你可以做一个tinyint(1)签名(对于-1)。

  3. 投票表中的ip列有点令人担忧。如果您通过IP管理“独特”投票,您是否考虑代理ips?这样的事情应该在帐户级别处理,因此来自同一代理IP的多个用户可以发出个人投票。

  4. 我不会做一个cronjob来确定showing列是否应标记为0或1.相反,我会在每次对该文章投票时发出一个计数。因此,如果有人投票或投票,计算故事的新价值,并将其存储在缓存中以备将来阅读。

答案 1 :(得分:1)

我会使用触发器(插入触发器)并在那里处理你的逻辑(在数据库本身)? 这将完全删除轮询代码(cron job)。 我还会保留你的外键(在VOTES中)与主键(在STORIES中)相同(至少是类型)?

从长远来看,使用触发器代替轮询将更加清晰。

您没有指定数据库,但在TSQL(对于SQL Server)中,它可能接近此

CREATE TRIGGER myTrigger 
ON VOTES
FOR INSERT
AS

DECLARE @I INT --HOLDS COUNT OF VOTES

DECLARE @IN VARCHAR(255) --HOLDS FK ID FOR LOOKUP INTO STORIES IF UPDATE REQUIRED

SELECT @IN = ITEM_NAME FROM INSERTED

SELECT @I = COUNT(*) FROM VOTES WHERE ITEM_NAME = @IN

IF (@I >= 10)

BEGIN

  UPDATE STORIES SET SHOWING = 1 WHERE ID = @IN --This is why your PK/FK should be refactored

END

答案 2 :(得分:1)

使用此查询,您将获得所有文章的列表以及包含相关投票数的列。

SELECT s.*, SUM(v.vote_value) AS votes_total
FROM stories AS s INNER JOIN votes AS v
ON v.item_name = s.id
GROUP BY v.vote

这样,您就可以创建一个视图,您可以在votes_total > 10上对其进行过滤,而无需使用cron作业。

或者您可以将其用作普通查询,如下所示:

SELECT * FROM (
  SELECT s.*, SUM(v.vote_value) AS votes_total
  FROM stories AS s INNER JOIN votes AS v
  ON v.item_name = s.id
  GROUP BY v.vote
) WHERE votes_total > 10;