2014-09-19 66 views
0

我試圖創建一個音樂家的排名系統,在我的MySQL表我讓他們列出像這樣的列表排名:找出一排中的行與不同價值觀

id genre artist   rating  votes 
1  rock pink floyd   138   25 
2  rock black sabbath  149   28 
3  pop  katy perry   98   12 
4  rock the who   72   14 

用戶可以打分一個1-10級的藝術家,在一次投票中,我只是將數字(1-10)作爲評級增加到表格中,並將投票增加1,因此爲了確定級別,我將用票數來分等級,成爲排名。

我明白如何創建一個顯示所有藝術家排名的概覽,但我試圖找到一種有效的方式來確定特定藝術家的排名。長篇小說:如果我是在黑色安息日子頁面上,我將如何確定它在rock類別中的排名?

我希望解釋是可以理解的。

+1

你似乎顯示黑色安息日輕微領先的Pink Floyd的。這顯然是錯誤的! ;-)不要讓我開始在凱蒂佩裏... – Strawberry 2014-09-19 14:38:21

+0

@Strawberry凱蒂佩裏是在流行類別,所以不計算;-)。 不幸的是,我不太確定從哪裏開始,我不期待在這裏準備好寫代碼,只是在正確的方向上的一個點。 – maricos 2014-09-19 14:44:47

回答

0
SELECT COUNT(mi.genre) + 1 rank 
    FROM musician m 
LEFT JOIN (
    SELECT genre, ROUND(COALESCE(rating/votes,0),10) rating_per_vote 
     FROM musician 
     ) mi 
     ON mi.genre = m.genre 
     AND mi.rating_per_vote > ROUND(COALESCE(m.rating/m.votes,0),10) 
    WHERE m.artist = 'black sabbath'; 

DEMO

UPDATE

實際上,你可以丟棄來自內表的ID,我做了些玩耍。 但是,您確實需要ROUND()以確保比較是正確的。

+0

我已經嘗試了與ID的那個,這很好!使用更新的解決方案時使用'ROUND()'代替速度更明智嗎? – maricos 2014-09-19 15:20:00

+0

不知道,對不起,但由於比較失敗沒有'ROUND()'..我擔心兩個'rating_per_vote's是相同的(但不同的ID)的情況。放入ROUND()會導致查詢按預期工作,添加ID只是一個解決辦法。你可以使用兩種方法(ids和'ROUND()'),但是我會對它進行基準測試,看看它是否有任何好處。 – Arth 2014-09-19 15:23:31

0

另一種解決方案,以較少的子查詢:

SELECT 
    m.artist, 
    r.rank, 
    r.average 
FROM 
    musician m 
JOIN 
    (
     SELECT 
      id, 
      @rank := @rank + 1 rank, 
      IF(votes = 0, 0, ROUND(rating/votes, 10)) average 
     FROM 
      musician, (SELECT @rank := 0) uv 
     WHERE genre = 'rock' 
     ORDER BY average DESC 
    ) r 
ON 
    r.id = m.id 
WHERE m.artist = 'black sabbath'