【问题标题】:Choosing data pseudo-randomly with even distribution以均匀分布伪随机选择数据
【发布时间】:2011-03-04 18:35:31
【问题描述】:

我目前正在从事一个中型网络项目,但遇到了问题。

我想要做的是显示一个问题和一张图片。我有一个(全局)问题列表和一个(全局)图像列表,应该针对所有图像询问所有问题。

就用户可以看到的问题和图像应随机选择。然而,来自答案(问题/图像对)的统计数据将用于研究目的。这意味着必须选择所有问题/图像对,以便答案将均匀分布在所有问题和所有图像中。

用户应该只能回答一次特定的问题/图像对。

我正在使用 mysql 数据库和 php。目前,我有三个数据库表:

tbl_images (image_id)

tbl_questions (question_id)

tbl_answers (answer_id, image_id, question_id, user_id)

其他列与此特定问题无关。

解决方案 1: 跟踪每个图像/问题的使用次数(在每个表中添加一列)。始终选择被问得最少的图片和问题。
问题: 我真正感兴趣的是图像问题之间的分布,反之亦然,而不是每个问题都是全局的。

解决方案 2: 添加另一个表,其中包含所有问题/图像对以及它被询问的次数。选择最低的组合(如果计数列按升序排序,则为第一行)。
问题: 不强制用户只能回答一次问题。也不会给用户选择随机的现象。

解决方案 3: 与 #2 相同,但将问题/图像/user_id 存储在表中。
问题: 性能问题(?),为每个用户浪费了大量空间。可能会有半大量的数据(数千个问题/图像和至少数百个用户)。

解决方案 4: 从所有可用内容中随机选择一个问题和图像。如果答案数量足够多,它们将均匀分布。
问题: 如果我添加一个新问题或图像,他们将不会得到比其他人更多的答案,因此永远不会赶上。我想要所有问题/图像对的统计数据数量均等。

解决方案 5: 加权随机。随机选择一些问题/图像对(例如大约 10 到 100 个),然后从中挑选出用户未回答的最佳(例如,最低的全局计数)。
问题: 不保证最近添加的问题或图像会很快得到很多答案。

解决方案 #5 可能是迄今为止我想出的最好的解决方案。
非常感谢您的意见,感谢您的宝贵时间。

【问题讨论】:

  • 我在上一个问题中得到了一些关于加权值的很好的答案。也许他们会帮助你。 stackoverflow.com/questions/4030427/…
  • P.S.编程中没有“真正的随机”之类的东西。只有伪随机(除非你可以使用自然随机生成器,即使那样,也可以说它只是随机的,因为我们不知道如何预测它。)

标签: php mysql sql performance


【解决方案1】:

根据我对您的问题的理解,我会选择 #1。但是,您不需要新列。我会创建一个 SQL 视图,因为听起来你无论如何都需要报告类似的事情。视图基本上是一个缓存选择,但其行为类似于表。因此,您将创建一个视图来保持每个图像回答的每个问题的总数:

DROP VIEW IF EXISTS "main"."view_image_question_count";
CREATE VIEW "view_image_question_count" AS 
SELECT a.image_id, a.question_id, SUM(b.question_id) as "total"
FROM answer AS a
INNER JOIN answer AS b ON a.question_id = b.question_id
GROUP BY a.image_id, a.question_id;

然后,您需要一种快速简便的方法来获得下一个最佳图像/问题组合:

DROP VIEW IF EXISTS "main"."view_next_best_question";
CREATE VIEW "view_next_best_question" AS 
SELECT a.*, user_id
    FROM view_image_question_count a
    JOIN answer USING( image_id, question_id )
    JOIN question USING(question_id)
    JOIN image USING(image_id)
ORDER BY total ASC;

现在,如果您需要报告您的图像以质疑性能,您可以通过以下方式进行:

SELECT * FROM view_image_question_count

如果您需要下一个最佳图像+问题来询问用户,您可以致电:

SELECT * FROM view_next_best_question WHERE user_id != {USERID} LIMIT 1

!= {USERID} 部分是为了防止收到用户已经回答的问题。 LIMIT 优化后只得到一个。

免责声明:可能有很多可以做的优化。我只是想发表一些想法。

另外,这是我用于测试的数据库转储。 http://pastebin.com/yutyV2GU

【讨论】:

  • 感谢您的回答,一个很好的解决方案。经过一些更改后,我让它工作了,最值得注意的是 SUM 函数只会将每个 id 的数值相加,而我想要计数。我可能还会添加一些额外的代码来处理从未被问过的问题(即不在答案表中)。再次感谢:)
  • 这已经处理了尚未回答的问题。因此,第二个视图上的所有连接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 2011-08-08
  • 1970-01-01
  • 2020-04-04
相关资源
最近更新 更多