Php 投票脚本,简化数据库查询的可能性

Php 投票脚本,简化数据库查询的可能性,php,mysql,database-design,Php,Mysql,Database Design,我有一个投票脚本,它将post_id和user_id存储在一个表中,以确定某个特定用户是否已经对某个帖子进行了投票,并在将来禁止他们 为此,我将执行以下3个查询 SELECT user_id, post_id from votes_table where postid=? AND user_id=? 如果未返回任何行,则: UPDATE post_table set votecount = votecount-1 where post_id = ? 然后 在网页上显示新votecount的步

我有一个投票脚本,它将post_id和user_id存储在一个表中,以确定某个特定用户是否已经对某个帖子进行了投票,并在将来禁止他们

为此,我将执行以下3个查询

SELECT user_id, post_id from votes_table where postid=? AND user_id=?
如果未返回任何行,则:

UPDATE post_table set votecount = votecount-1 where post_id = ?
然后

在网页上显示新votecount的步骤

有更好的方法吗?3个查询严重降低了用户的投票体验

编辑

  • 在投票表中,投票id是主键
  • 在post表中,post_id是主键
  • 还有其他加快速度的建议吗

您可以合并前两个查询:

UPDATE  post
SET     votecount = votecount - 1
WHERE   post_id = ?
        AND post_id NOT IN
        (
        SELECT  post_id
        FROM    votes_table
        WHERE   user_id = ?
        )
您仍然需要运行第三个

确保在
投票表(用户id,帖子id)
帖子(帖子id)
上有唯一的索引或
主键


最有可能的是,您当前的查询速度缓慢是由于缺少这些索引造成的。

Quassnoi的答案将非常低效,因为它将用户曾经投票的每个帖子id都拉到了“不在”中

UPDATE 
    dbo.Post
SET 
    VoteCount = VoteCount + 1 -- Must be +1 right? Not minus 1?
FROM
    dbo.Post p
WHERE
    NOT EXISTS
        (
        SELECT
            v.PostID
        FROM
            dbo.Votes_Table v
        WHERE
            v.PostID = p.PostID
        AND v.User_ID = ?
        )
WHERE
    p.PostID = ?

IF(@@ROWCOUNT = 1)
    PRINT 'No previous vote, votes incremented'
ELSE
    PRINT 'User has already voted, votes not incremented'

就我个人而言,我会认真地重新考虑在投票桌上维持计票

我在投票表中有一个投票id。将其放入主键中?在投票表中,投票id已经是主键。在post表中,post_id也是主键。我遗漏了什么吗?@Sev:
创建唯一索引投票\u user\u post ON vows\u table(user\u id,post\u id)
@Bill:除了主键之外,您正在创建一个新的唯一索引吗?如果是这样的话,你能告诉我或链接我为什么需要同时拥有主键和唯一索引吗?@Sev:如果用户只能对帖子投一次赞成票或反对票,你需要创建一个唯一索引来监督这个约束。此索引还将加快查询速度,因为它将有助于立即在表中找到用户/帖子对。如果您不引用其他表中的
投票表
,您可以将(
用户id
发布id
)设置为
主键(因为这是一个多对多链接表)。为什么要从投票计数中减去一个?因为你已经在投票表中添加了一些东西,比如记录?如果某个帖子被否决,我需要从计票中减去1。有更好的建议吗?正如我在回答中提到的,不要保留post_table.vote_count。当您需要计数时,将选票表中的加减票数相加。@Mark-如果每个帖子都这样做怎么办?有点像现在这样。你还是每次都运行一个sum,而不是将其保存在DB中?是的,请参阅下面的注释。是否值得在一个新问题中扩展您的场景,并更详细地介绍模式和功能?这将给人们一个更好的机会来建议替代方法。减1,因为我指的是否决票脚本。同样的概念。而且,我应该指定我的数据库不是MySQLMSSQL@Mark:为什么您认为这样做效率低下?@Quassnoi因为您选择的是用户在子查询中进行的每一次投票的post_id。如果那个用户是你,而站点是stackoverflow,那是2200行而不是1行。@Mark-你会重新考虑在post表上保持投票计数吗?那么,您是否建议在投票表上运行select sum(),而不是针对每个帖子?
UPDATE 
    dbo.Post
SET 
    VoteCount = VoteCount + 1 -- Must be +1 right? Not minus 1?
FROM
    dbo.Post p
WHERE
    NOT EXISTS
        (
        SELECT
            v.PostID
        FROM
            dbo.Votes_Table v
        WHERE
            v.PostID = p.PostID
        AND v.User_ID = ?
        )
WHERE
    p.PostID = ?

IF(@@ROWCOUNT = 1)
    PRINT 'No previous vote, votes incremented'
ELSE
    PRINT 'User has already voted, votes not incremented'