【问题标题】:Need support with figuring out a query for a cron job需要支持找出 cron 作业的查询
【发布时间】:2011-12-21 22:28:39
【问题描述】:

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

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

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

那么任何人都可以建议一个可以完成任务的 cron 作业吗?

这是我的数据库结构:

故事表


投票表


编辑:

例如“故事”表中的这一行:

id| 12
st_auth | 作者姓名
st_date | 故事日期
st_title| 故事标题
st_category| 故事类别
st_body| 故事正文
showing| 0 表示未经证实,1批准

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

id| 83 item_name| 12(文章 ID) vote_value| 1 表示赞成 -1 表示反对 ...

【问题讨论】:

  • 您是否有机会从每个表中包含一个示例行?我想提供一个解决方案,但需要确保我们在同一页面上。
  • 可以使用 MySQL 触发器
  • @Atticus 我是 php 和 mySql 的新手,我听说过它们,但我还不知道如何使用它们。

标签: php mysql cron vote


【解决方案1】:

几件事:

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

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

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

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

【讨论】:

  • +1。确切地说,item_name 应该是 int 而不是 varchar(我不确定在这种情况下连接是自动转换还是失败);另外,我会通过每次重新计算sum 的投票来完全避免 cronjob/trigger 的事情——也许使用应该由服务器缓存的视图。
【解决方案2】:

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

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;

【讨论】:

    【解决方案3】:

    我会使用触发器(插入触发器)并在那里处理您的逻辑(在数据库本身中)? 这将完全删除轮询代码(cron 作业)。 我还会让您的外键(在 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
    

    【讨论】:

    • 哇,抱歉,我在这里迷路了,所以你说我应该在 item_name 上使用 int(11) 而不是 varchar(255) 对吗?比我在哪里声明这个触发器?我以前从未使用过它们,我是否在 phpMyAdmin 的某个地方输入它(我用它来管理我的数据库)。抱歉有这么多问题,但我对触发器完全陌生。
    • @user1110757 db 在标签中指定,它是 MySQL。致 Ilya Knaup:在此处阅读有关 triggers in mysql 的信息。我对 mysql 中的触发器没有太多经验,但是,在我看来,它们不值得信任,因为它们是相当新的。另外,据我所知,在 phpMyAdmin 中,您只能手动创建/更改触发器(运行 DDL 查询),没有用于管理触发器的 UI
    • @talereader:根据我的经验,触发器非常稳定,但是在数据库级别添加这样的业务逻辑时会变得混乱,尤其是在调试时。很多时候,逻辑被忽略了,开发人员浪费时间查看代码库。
    • @Digital Precision 是的,开发人员可能经常忘记他们自己放置的触发器,尤其是在 MySQL 中。但是我习惯于在 Firebird / Delphi 上进行开发,并且在数据库级别(超过 100 个存储过程和触发器)发生了很多事情,因为更改数据库比重新编译代码容易得多。所以触发了ftw,但如果理解不正确,它们可能会很痛苦。如果有时间,我一定会给 MySQL 触发器一个机会。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    • 2014-04-28
    相关资源
    最近更新 更多