当前位置: 首页 > 面试题库 >

选择30个随机行,其中总和= x

居乐池
2023-03-14
问题内容

我有桌子

items
id int unsigned auto_increment primary key,
name varchar(255)
price DECIMAL(6,2)

我希望从此表中至少获得30个随机物品,其中总价格等于500,那么实现此目的的最佳方法是什么?

我看过了这个解决方案,它看起来也有类似的问题。MySQL选择3个随机行,其中三行之和小于值

我想知道是否还有其他更易于实施和/或更有效的解决方案


问题答案:

如果您的产品列表满足以下 假设, 则有解决方案:

您有所有价格在0.00到500.00之间的产品。例如。0.01、0.02等至499.99。或0.05、0.10等至499.95。

该算法基于以下内容:

在总计为S的n个正数的集合中,其中至少一个小于S除以n(S / n)

在这种情况下,步骤为:

  1. 随机选择价格<500/30的产品。得到它的价格,比方说X。
  2. 随机选择价格<(500-X)/ 29的产品。得到它的价格,假设Y。
  3. 随机选择价格<(500-X-Y)/ 28的产品。

重复此29次,即可获得29个产品。对于最后一种产品,选择一个 价格=剩余价格的产品
。(或价格<=剩余价格和按价格降序排列的订单,希望您能获得足够的价格)。

对于表项:

获得随机产品的最高价格:

CREATE PROCEDURE getRandomProduct (IN maxPrice INT, OUT productId INT, productPrice DECIMAL(8,2))
BEGIN
   DECLARE productId INT;
   SET productId = 0;
       SELECT id, price INTO productId, productPrice
       FROM items
       WHERE price < maxPrice
       ORDER BY RAND()
       LIMIT 1;
END

获得29个随机产品:

CREATE PROCEDURE get29products(OUT str, OUT remainingPrice DECIMAL(8,2))
BEGIN
  DECLARE x INT;
  DECLARE id INT;
  DECLARE price DECIMAL(8,2);
  SET x = 30;
  SET str = '';
  SET remainingPrice = 500.00;

  REPEAT
    CALL getRandomProduct(remainingPrice/x, @id, @price);
    SET str = CONCAT(str,',', @id);
    SET x = x - 1;
    SET remainingPrice = remainingPrice - @price;
    UNTIL x <= 1
  END REPEAT;
END

调用过程

CALL `get29products`(@p0, @p1); SELECT @p0 AS `str`, @p1 AS `remainingPrice`;

最后尝试找到最后一个达到500的产品。

或者,您可以选择28并在提供的链接问题上使用解决方案,以得到一对总和为剩余价格的产品。

请注意,允许 重复的 产品。为了避免重复,您可以getRandomProduct使用已经找到的产品的附加IN参数进行扩展,并添加条件 NOT
IN
来排除它们。

更新 :您可以 克服上述限制 ,以便 始终 使用下面第二部分所述的cron进程 找到总计为500集合

第二部分: 使用cron流程

以@Michael Zukowski的建议为基础,您可以

  • 创建一个表来保存找到的集合
  • 定义运行上述算法多次(例如10次)的cron进程。每5分钟
  • 如果找到与总和匹配的集合,请将其添加到新表中

这样,您可以找到 总精确等于500的 集合。当用户发出请求时,您可以从新表中选择一个随机集合。

即使匹配率达到20%,一个cron进程也会在24小时内每5分钟运行该算法10次,您可以收集500多个集合。

我认为使用cron流程具有以下优点和缺点:

优点

  • 查找完全匹配
  • 客户未要求处理
  • 即使匹配率较低,您也可以找到多个收藏集

缺点

  • 如果价格数据经常更新,您可能会得出不一致的结果,也许使用cron流程将行不通。
  • 必须丢弃或过滤旧收藏
  • 每个客户端可能不会是随机的,因为不同的客户端可能会看到相同的集合。


 类似资料:
  • 问题内容: 我正在使用PHP和MySQL创建一个简单的Web应用程序。在其中,我需要以随机顺序从表中随机选择一小组行。如何使用MySQL实现此类目标? 问题答案: SELECT * FROM table ORDER BY RAND() LIMIT 10;

  • 问题内容: 我有一个包含约50,000行的SQL Server表。我想随机选择大约5,000行。我想到了一种复杂的方法,用“随机数”列创建一个临时表,将我的表复制到该表中,遍历该临时表并用来更新每一行,然后从该表中选择随机数列< 0.1。我正在寻找一种更简单的方法,如果可能的话,可以在一个语句中进行说明。 本文建议使用该功能。这看起来很有希望,但是我看不到如何可靠地选择一定百分比的行。 有人做过吗

  • 问题内容: 我看到了许多与此主题有关的主题,但在了解如何做到这一点上一直没有成功。 例如,如果我有此表: 并且我只想显示“一个”类中的X个随机行,我该怎么做? 注意 :这是一张大桌子,所以我不想使用。 问题答案: 如您所知,大多数人推荐的解决方案无法扩展到大型表。 我在《SQL反模式:避免数据库编程的陷阱》一书中介绍了该解决方案和其他解决方案。 如果要使用PHP进行此操作,则可以执行以下操作(未测

  • 问题内容: 如何选择前5个随机元素 但它需要所有随机元素。我只想要第一个5。 还有另一种方法可以做同样的事情吗? 问题答案: 这是从jQuery选择中获取5个随机元素的方法,无需插件! 此时,您已经从jQuery返回的所有LI中随机选择了5个DomElement 然后,您可以对它们进行任何操作, 例如更改其颜色: 或显示其合并的文本内容:

  • 问题内容: 我正在使用SQL Server 2012,并且正在尝试执行以下操作: 因此,换句话说,我想从表中选择具有指定的截止日期和日期的随机行,并在里程总和等于或大于该数字时停止:3250 问题答案: 由于您使用的是SQL Server 2012,因此这是一种无需循环的简单方法。 SQLfiddle演示-多次单击“运行SQL”以查看随机结果。

  • 问题 你想从一个序列中随机抽取若干元素,或者想生成几个随机数。 解决方案 random 模块有大量的函数用来产生随机数和随机选择元素。 比如,要想从一个序列中随机的抽取一个元素,可以使用 random.choice() : >>> import random >>> values = [1, 2, 3, 4, 5, 6] >>> random.choice(values) 2 >>> random