Keeping in mind that sql queries have high fixed costs per query, I'd do it like this:
use one sql query to get a list of
songs that are ordered by length
(for example, a list of all songs
between x - y seconds long, up
to a max of z songs in total).
create a function that generates a playlist from that list of songs, by selecting songs from it in a way that follows the pattern outlined by your curve above.
Maybe something like this?
function makePlaylist(array songList,int playListLength,function curve)
int x=songList[0].length;
array playList=new array();//empty array
int max=getHighestBpmFromList(songList);//getHighestBpmFromList implementation not shown here
song closestMatch;
while (playList.length<playListLength)
currentLength=song.length
optimalBPM=-(x-songList[0].length)^2+max;//your curve as described above
closestMatch=findClosestMatch(optimalBPM);//findClosestMatch would find a song
//in the list whose bpm is as close
//as possible to what the bpm
//should be at x on the curve
//(maybe binary search, since
//the list is sorted)
playList.push(closestMatch);
x++
return playList;