【问题标题】:Block-wise and row-wise shuffling in MySQLMySQL中的逐块和逐行改组
【发布时间】:2015-08-12 21:29:37
【问题描述】:

有没有办法在 mySQL 中按块对结果集的行进行洗牌?

为了说明:所需的查询将以四种可能的顺序之一随机返回以下四行(但不是其他可能的顺序,例如项目 4 永远不应在项目 3 之前)。

原始订单,A 在 B 之前,item1 在 item2 之前

item,   b_order,    i_order
item1,  A,          1
item2,  A,          1
item3,  B,          1
item4,  B,          2

A 在 B 之前,item2 在 item1 之前

item2,  A,          1
item1,  A,          1
item3,  B,          1
item4,  B,          2

B 在 A 之前,item2 在 item1 之前

item3,  B,          1
item4,  B,          2
item2,  A,          1
item1,  A,          1

B 在 A 之前,item1 和 item2 没有交换

item3,  B,          1
item4,  B,          2
item1,  A,          1
item2,  A,          1

我想可能有一种比较优雅的方法来解决这个问题,通过使用

 SELECT * FROM items ORDER BY random_number_for_each_block, i_order, RAND()

我还没弄清楚如何生成这个“random_number_for_each_block”变量。

【问题讨论】:

  • 您的问题是什么?您有三个不同的结果集,但我不明白您要做什么。写一个查询返回所有三个?指定参数以获取一个或另一个?
  • @GordonLinoff 我的目标是编写一个随机返回四个枚举结果集之一的查询。当然,在实际情况下,这些块随机、行随机的实验设计是任意复杂的。我试图澄清这个问题。
  • 你在“原始订单”中失去了我

标签: mysql


【解决方案1】:

假设我们有

CREATE TABLE `origin` (
  `item` varchar(10) DEFAULT NULL,
  `b_order` varchar(4) DEFAULT NULL,
  `i_order` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

你可以这样做:

SELECT 
  *, 
  @b_rand  := IF(b_order!=@current, FLOOR(1000*RAND()), @b_rand) AS factor,
  @current := b_order AS current, 
  @b_rand + RAND() AS ordinal
FROM
  (SELECT *
   FROM origin
   ORDER BY b_order) AS ordered
CROSS JOIN
  (SELECT @b_rand:=FLOOR(1000*RAND())) AS init
ORDER BY ordinal

如果您已经知道在初始状态下它们按b_order 分组,则不需要按块排序项目的子查询。但拥有它更安全。

检查fiddle(块是分组的,但块顺序是随机的;块内的项目是随机排序的)

【讨论】:

  • 谢谢。我将数据添加到 SQL 查询中以使其更易于测试。不幸的是,您的解决方案不起作用,它只是完全随机地洗牌。原因:因子变量包含每个行/块的相同随机数。另外,“当前”这一行似乎是多余的?
  • 它对我来说工作正常,我会尝试准备一个小提琴。 @current 不是多余的,需要确定块边界所以是否需要更新因子
  • 这很奇怪!你的小提琴做块洗牌。我现在也看到了current 的必要性。我在我的 Mac 上使用 MySQL 5.62(正在通过 PHPmyadmin 进行测试),但它不起作用(即因子总是相同的数字)。在小提琴中,这些项目并没有按照我想要的块进行洗牌(可能我不清楚这一点),但我可以fix that自己(除非你认为我的修复有问题)。
  • 在我的小提琴中,块内的项目顺序是随机的。要么我不明白出了什么问题,要么要求不明确
  • 是的,要求不明确,抱歉。如果你看到我的小提琴,我想会更清楚:我想要按块打乱的项目,然后在按 i_order 排序的块内,如果相同(即 item1 和 item2),在块内打乱。第 4 项应始终遵循第 3 项。我的问题中的 4 个结果集确实是我想要的唯一可能的结果集。
猜你喜欢
  • 1970-01-01
  • 2018-10-10
  • 2018-07-25
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-27
  • 1970-01-01
相关资源
最近更新 更多