2012-10-18 27 views
0

我需要根據其流派生成歌曲列表。每個流派在列表中返回多少取決於用戶如何加權。根據x個權重選擇x個隨機行

所以他們可以設置...

Rock - 5 out of 10 
Pop - 2 out of 10 
Dance - 1 out of 10 
Folk - 10 out of 10 

在數據庫表中的每個軌道具有genre_id

Rock = 1 
Pop = 2 
Dance = 3 
Folk = 4 

他們也可以選擇多少個軌道返回,因此它可能是10 ,20 ...最多100.

我有2個表

TRACKS 
id (INT) 
track_name (VARCHAR) 
genre_id (INT) 

GENRES 
id (INT) 
name (VARCHAR) 

我使用MySQL和PHP來實現這一點,任何幫助將是巨大的

+0

顯示你的表結構。 –

回答

1

這工作相當好。然而,在某些情況下,歌曲總數會有舍入誤差(從不超過1)。

/* 
* It's more likely to fill the first two arrays from a query, but for 
* the example I defined them like 
* genreId => value 
*/ 
$genres = array(
    1 => 'rock', 
    2 => 'pop', 
    3 => 'dance', 
    4 => 'folk', 
    27 => 'classical' 
); 

$pointsPerGenre = array(
    1 => 5, //rock, 5 out of 10 
    2 => 2, //pop, 2 out of 10 
    3 => 1, //etc... 
    4 => 10, 
    27 => 7 
); 

$totalPoints = array_sum($pointsPerGenre); 

$numberOfSongs = 20; 

$songsPerPoint = $numberOfSongs/$totalPoints; 

$songsPerGenre = array(); 
foreach(array_keys($genres) as $genreId) 
{ 
    $songsPerGenre[$genreId] = round($pointsPerGenre[$genreId] * $songsPerPoint); 
} 


$queryParts = array(); 
foreach($songsPerGenre as $genreId => $numberOfSongsPerGenre) 
{ 
    $queryParts[] = "(SELECT * FROM TRACKS WHERE genre_id = $genreId ORDER BY RAND() LIMIT $numberOfSongsPerGenre)"; 
} 

$query = implode("\nUNION\n", $queryParts); 

這將輸出下面的查詢(在這裏你可以看到舍入誤差,用戶會收到在這種情況下,一個獎金歌曲):

(SELECT * FROM TRACKS WHERE genre_id = 1 ORDER BY RAND() LIMIT 4) 
UNION 
(SELECT * FROM TRACKS WHERE genre_id = 2 ORDER BY RAND() LIMIT 2) 
UNION 
(SELECT * FROM TRACKS WHERE genre_id = 3 ORDER BY RAND() LIMIT 1) 
UNION 
(SELECT * FROM TRACKS WHERE genre_id = 4 ORDER BY RAND() LIMIT 8) 
UNION 
(SELECT * FROM TRACKS WHERE genre_id = 27 ORDER BY RAND() LIMIT 6) 
+0

謝謝你的幫助!現在對我來說很有意義。我想我會用php rand/limit取代ORDER BY RAND()的 – Mark