MySQL 将 rand() 的顺序修改为其他方法
MySQL modifying order by rand() to other methods
我现在正尝试从每个分组列数组中随机选择,机会后跟每一行的权重。例如,我有一个像这样的 table (DemoTable):
http://sqlfiddle.com/#!9/23470/3/0
姓名
州
年级
体重
约翰
纽约
100
1
利亚姆
纽约
90
2
奥利维亚
纽约
90
3
艾玛
纽约
80
4
詹姆斯
CA
10
1
亨利
CA
20
1
米娅
新泽西州
50
1
艾娃
新泽西州
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;
它的结果是:
姓名
州
年级
体重
random_val
约翰
纽约
100
1
80
利亚姆
纽约
90
2
80
奥利维亚
纽约
90
3
80
艾玛
纽约
80
4
90
詹姆斯
CA
10
1
20
亨利
CA
20
1
10
米娅
新泽西州
50
1
30
艾娃
新泽西州
30
4
30
虽然,我想知道是否有任何其他方法,如 join 或 union,而不是单独使用 order by rand()。
是否有任何其他方法来修改我的 MySQL 查询以提供相同的结果?
我整天都在寻找解决这个问题的方法,但找不到合适的方法;这就是为什么我在这里请求帮助。
如果能得到一些建议,我将不胜感激。
我第一次尝试使用分析函数,但我怀疑你的函数在更大的数据集上更快...
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
我现在正尝试从每个分组列数组中随机选择,机会后跟每一行的权重。例如,我有一个像这样的 table (DemoTable): http://sqlfiddle.com/#!9/23470/3/0
姓名 | 州 | 年级 | 体重 |
---|---|---|---|
约翰 | 纽约 | 100 | 1 |
利亚姆 | 纽约 | 90 | 2 |
奥利维亚 | 纽约 | 90 | 3 |
艾玛 | 纽约 | 80 | 4 |
詹姆斯 | CA | 10 | 1 |
亨利 | CA | 20 | 1 |
米娅 | 新泽西州 | 50 | 1 |
艾娃 | 新泽西州 | 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;
它的结果是:
姓名 | 州 | 年级 | 体重 | random_val |
---|---|---|---|---|
约翰 | 纽约 | 100 | 1 | 80 |
利亚姆 | 纽约 | 90 | 2 | 80 |
奥利维亚 | 纽约 | 90 | 3 | 80 |
艾玛 | 纽约 | 80 | 4 | 90 |
詹姆斯 | CA | 10 | 1 | 20 |
亨利 | CA | 20 | 1 | 10 |
米娅 | 新泽西州 | 50 | 1 | 30 |
艾娃 | 新泽西州 | 30 | 4 | 30 |
虽然,我想知道是否有任何其他方法,如 join 或 union,而不是单独使用 order by rand()。
是否有任何其他方法来修改我的 MySQL 查询以提供相同的结果?
我整天都在寻找解决这个问题的方法,但找不到合适的方法;这就是为什么我在这里请求帮助。
如果能得到一些建议,我将不胜感激。
我第一次尝试使用分析函数,但我怀疑你的函数在更大的数据集上更快...
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