1

我被要求向应用程序添加功能,让用户在两个选项之间进行投票:A 和 B。这些问题的表格非常基本:

QUESTIONS
question_id (PK)
option_id_1(FK)
option_id_2(FK)
urgent (boolean)

每次用户投票时,用户投票的数据都会存储在一个同样简单的表中:

USER VOTES
vote_id (PK)
user_id (FK)
question_id (FK)

当用户请求新问题时选择出现哪个问题的算法很复杂,但出于我们的目的,我们可以假设它是随机的。那么,问题呢?

每个用户将对许多问题进行投票。可能数百,甚至数千。我需要确保没有用户收到他们已经投票过的问题,而我想这样做的唯一方法是,我猜,将服务器打到遗忘状态。具体来说,类似:

SELECT * from questions WHERE question_id NOT in (SELECT question_id from user_votes WHERE user_id = <user_id>) ORDER BY RAND() LIMIT 1. 

[注意:RAND() 实际上不在查询中 - 它只是作为稍微复杂的 (order_by) 的替代品。]

因此,请记住,许多用户很可能已经对数百个甚至数千个问题进行了投票,并且不可能按固定顺序呈现问题......关于如何在不击败我的服务器的情况下排除投票问题的任何想法进入地下?

感谢所有建议 - 非常感谢。

4

2 回答 2

3

JOIN运算符的性能比 MySQL 中的嵌套查询好得多(可能会随着最新的 MySQL 版本而改变,但如果您遇到性能问题,我猜我的说法仍然成立)

您可以做的只是将投票留在问题上,然后只选择那些没有投票的记录(没有人投票):

SELECT * 
FROM questions q 
LEFT JOIN user_votes uv ON 
  uv.question_id = q.question_id AND
  uv.user_id = '<user_id>'
WHERE vote_id IS NULL
于 2012-04-19T12:51:21.103 回答
1

RAND() 很讨厌,但是这可能会减轻问题,同时为您提供所需的结果。看到你提到 RAND() 是一个例子,我真的不能提供比下面更具体的建议,但是替换 ORDER BY 应该可以正常工作。

您能够限制内部查询中的行数越多,整个查询的执行速度就越快。

SELECT
    q.*
FROM (
    -- First get the questions which have not been answered
    SELECT 
        questions.*
    FROM questions 
    LEFT JOIN user_votes 
        ON user_votes.question_id = questions.question_id
        AND user_votes.user_id = <user_id>
    WHERE user_votes.user_id IS NULL
) q
-- Now get a random 1.  I hate RAND().
ORDER BY RAND()
LIMIT 1
于 2012-04-19T12:54:21.023 回答