我有一个表keywords
,其中包含keyword
列和weight
列。我的目标是随机选择一个keyword
,但要考虑其weight
(概率)。我找到了两种方法来解决这个问题,后一种方法更优雅(并且消耗更少的资源) - 但我不能让它运行。看看你自己。
表和记录:
CREATE TABLE IF NOT EXISTS `keywords` (
`keyword` varchar(100) COLLATE utf8_bin NOT NULL,
`weight` int(11) NOT NULL,
UNIQUE KEY `keywords` (`keyword`),
KEY `rate` (`weight`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
INSERT INTO `keywords` (`keyword`, `weight`) VALUES
('google', 50),
('microsoft', 20),
('apple', 10),
('yahoo', 5),
('bing', 5),
('xing', 5),
('cool', 5);
查询1
消耗更多的资源,我处理5k +记录。来源是Why would this MySQL query using rand() return no results about a third of the time?:
SELECT * FROM `keywords` ORDER BY -LOG(1.0 - RAND()) / weight LIMIT 1
查询2
将权重汇总到@weight_sum
。从该范围内将@weight_point
设置为RAND()
个数字。循环浏览所有记录,从weight
中减去@weight_pos
并将@keyword
设置为当前keywords.keyword
。直到@weight_pos < 0
。然后它保留keyword
。来源是Random Weighted Choice in T-SQL
SET @keyword = 0;
SET @weight_sum = (SELECT SUM(weight) FROM keywords);
SET @rand = RAND();
SET @weight_point = ROUND(((@weight_sum - 1) * @rand + 1), 0);
SET @weight_pos = @weight_point;
SELECT
keyword,
weight,
@keyword:=CASE
WHEN @weight_pos < 0 THEN @keyword
ELSE keyword
END AS test,
(@weight_pos:=(@weight_pos - weight)) AS curr_weight,
@weight_point,
@keyword,
@weight_pos,
@rand,
@weight_sum
FROM
keywords;
请在此处查看phpmyadmin结果http://postimg.org/image/stgpd776f/
我的问题
如何获取@keyword
中的值,或者test
列最终保留的内容?之后添加SELECT @keyword
不会改变任何内容。
答案 0 :(得分:0)
好吧,我认为我的问题或多或少是一个基本的mysql问题。我通过将上面的SELECT语句封装到另一个SELECT中来实现我想要的,然后根据我搜索的内容过滤第一个SELECT的结果。对不起,打扰你。请参阅查询:
SET @keyword = 0;
SET @weight_sum = (SELECT SUM(weight) FROM keywords);
SET @rand = RAND();
SET @weight_point = ROUND(((@weight_sum - 1) * @rand + 1), 0);
SET @weight_pos = @weight_point;
SELECT t.test FROM (
SELECT
keyword,
weight,
@keyword:=CASE
WHEN @weight_pos < 0 THEN @keyword
ELSE keyword
END AS test,
(@weight_pos:=(@weight_pos - weight)) AS curr_weight,
@weight_point,
#@keyword,
@weight_pos,
@rand,
@weight_sum
FROM
keywords
) AS t
WHERE
t.curr_weight < 0
LIMIT
1;