【问题标题】:MySQL modifying order by rand() to other methodsMySQL 通过 rand() 将 order 修改为其他方法
【发布时间】:2021-09-05 20:16:55
【问题描述】:

我现在尝试从每个分组的列数组中进行随机选择,机会后面是每行的权重。例如,我有一个这样的表(DemoTable): http://sqlfiddle.com/#!9/23470/3/0

Name State Grade Weight
John NY 100 1
Liam NY 90 2
Olivia NY 90 3
Emma NY 80 4
James CA 10 1
Henry CA 20 1
Mia NJ 50 1
Ava NJ 30 4

对于 State = 'NY',有四行带有等级数组:[100, 90, 90, 80] 和权重 [1, 2, 3, 4],分别。因此,在其州组中,80 人被选中的机会最大,而 100 人被选中的机会最少。 我查询了它:

SELECT a.*,
(SELECT b.Grade FROM DemoTable b WHERE a.State = b.State 
ORDER BY RAND() * -b.Weight LIMIT 1) AS 'random_val' FROM DemoTable a;

它与结果一起工作:

Name State Grade Weight random_val
John NY 100 1 80
Liam NY 90 2 80
Olivia NY 90 3 80
Emma NY 80 4 90
James CA 10 1 20
Henry CA 20 1 10
Mia NJ 50 1 30
Ava NJ 30 4 30

不过,我想知道是否有其他方法,例如 join 或 union,而不是单独使用 order by rand()。
有没有其他方法可以修改我的 MySQL 查询以提供相同的结果?
我整天都在寻找解决这个问题的方法,但找不到正确的方法;这就是我在这里寻求帮助的原因。
如果我能得到一些建议,我将不胜感激。

【问题讨论】:

  • @philipxy - 你指的民间理论是什么? (在 MySQL 中 RAND() 为每一行独立执行,如手册中所示...dev.mysql.com/doc/refman/5.7/en/…
  • @Jay 在 MySQL8 中我能想到几个选择, 是 MySQL 5.7 (将近六岁吗? ,并在三年前被 MySQL 8.0 取代).
  • @MatBailie 它不一定是 MySQL 5.7。您能否提供一些使用 MySQL8 的提示?
  • 显示所需的输出。它是否必须只包含 3 行,每个州一行?
  • @Akina,它确实显示了预期的结果;源表加上一列

标签: mysql sql join random union


【解决方案1】:

我第一次尝试使用分析函数,虽然我怀疑你的比更大的数据集更快...

WITH
  ranged AS
(
  SELECT
    *,
    SUM(weight) OVER (PARTITION BY state ORDER BY id) - weight   AS weight_range_lower,
    SUM(weight) OVER (PARTITION BY state ORDER BY id)            AS weight_range_upper,
    SUM(weight) OVER (PARTITION BY state            ) * rand()   AS rand_threshold
  FROM
    DemoTable
)
SELECT
  ranged.*,
  lookup.grade   AS random_grade
FROM
  ranged
INNER JOIN
  ranged  AS lookup
    ON  lookup.state               = ranged.state
    AND lookup.weight_range_lower <= ranged.rand_threshold
    AND lookup.weight_range_upper >  ranged.rand_threshold
ORDER BY
  ranged.id

或者,如果您希望同一状态的所有成员都获得相同的 random_grade...

SELECT
  *,
  FIRST_VALUE(grade) OVER (PARTITION BY state ORDER BY weight * rand() DESC)
FROM
  DemoTable
ORDER BY
  id

https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=133f9e86b013a477ac342d0295132dd5

【讨论】:

  • 非常感谢您的回答。我想不出用这种方式。给我同样的结果,效果很好:)
猜你喜欢
  • 2011-02-22
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 2012-06-09
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多