2013-04-18 45 views
0

我有一個表keywords,列keywordweight。我的目標是隨機選擇一個keyword,但將其視爲weight(概率)。我發現了兩種方法來解決這個問題,後者更優雅(並且消耗更少的資源) - 但我沒有讓它運行。看看你自己。mysql加權隨機結果 - 如何在SELECT後獲得更改的變量值

表和記錄:

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

佔用更多的ressources,我在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_pointRAND()數字。循環遍歷所有記錄,從@weight_pos減去weight,並將@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/

phpmyadmin

我的問題

我如何獲得在@keyword什麼test列包含在最終的價值,或?事後添加SELECT @keyword不會改變任何內容。

回答

0

好的,我想我的問題或多或少是一個基本的mysql問題。通過將上面的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;