2014-12-19 45 views
0

我有一個表是這樣的:次序等級更新

id name incidence placeRef 
1  John 10   1 
2  Ann  9   1 
3  Paul 9   1 
4  Carl 8   1 
5  John 4   1 
6  Ann  4   1 
7  Paul 7   1 
8  Carl 1   1 

我希望這些使用ordinal ranking method排名。這將增加行列到我的表中,因此:

id name incidence placeRef rank 
1  John 10   1   1 
2  Ann  9   1   2 
3  Paul 9   1   2 
4  Carl 8   1   4 
5  John 4   1   2 
6  Ann  4   1   2 
7  Paul 7   1   1 
8  Carl 1   1   4 

這怎麼能實現?

N.B.我將回答我自己的問題,但想知道是否有人有更好的解決方案,因爲這有點不好意思;儘管我發現了很多推薦黑客的帖子。

+0

您的SQL語句在哪裏? – Raptor 2014-12-19 02:35:03

+0

花了一段時間對我進行註釋。 – 2014-12-19 02:44:53

回答

1

以下工作:

UPDATE names 
JOIN (SELECT * FROM names ORDER BY placeRef, incidence DESC) AS p ON p.id = names.id, 
(SELECT @curRank := 0, @nextRank := 0, @prevInc := 9999999999, @prevPlace := 0) AS v 
SET 
names.rank = IF( @prevPlace != p.placeRef, @curRank := 0, 0), 
names.rank = IF( @prevPlace != p.placeRef, @nextRank := 0, 0), 
names.rank = IF( @prevInc = p.incidence, @nextRank := @nextRank + 1, @curRank := @nextRank := @nextRank + 1), 
names.rank = IF( @prevInc = p.incidence, @curRank := @curRank, @curRank := @nextRank), 
names.incidence = @prevInc := names.incidence, 
names.placeRef = @prevPlace := names.placeRef; 

說明:

UPDATE names 

1 - 設置表進行更新

JOIN (SELECT * FROM names ORDER BY placeRef, incidence DESC) AS p ON p.id = names.id, 

2 - 這使得有結果的虛擬表排序的,所以該排名可以應用

(SELECT @curRank := 0, @nextRank := 0, @prevInc := 9999999999, @prevPlace := 0) AS v 

3 - 這將一些變量將被用來告訴何時incrament並重置排名

names.rank = IF( @prevPlace != p.placeRef, @curRank := 0, 0), 

4 - 這是當前等級重置爲0黑客攻擊時的MySQL迭代到一個新的地方

names.rank = IF( @prevPlace != p.placeRef, @nextRank := 0, 0), 

5 - 這是下一個等級重置爲0黑客攻擊時的MySQL迭代到一個新的地方

names.rank = IF( @prevInc = p.incidence, @nextRank := @nextRank + 1, @curRank := @nextRank := @nextRank + 1), 

6 - 這是一個更新下一個和真正水流黑客攻擊在當前發病率是一樣的前面發生

names.rank = IF( @prevInc = p.incidence, @curRank := @curRank, @curRank := @nextRank), 

7 NT行列 - 設置職級相同,最後的排名時,其發病率是一樣的前面,或者如果它不是遞增等級」牛逼

names.incidence = @prevInc := names.incidence, 

8 - 這是設置一個變量包含先前發生黑客攻擊,因此,我們可以告訴在未來itteration

names.placeRef = @prevPlace := names.placeRef; 

9做的 - 這是一個黑客ŧ帽子設置一個變量來包含以前的地方,所以我們可以告訴下一步做什麼

2

你可以用變量或相關的子查詢來做到這一點。子查詢方法如下:

select t.*, 
     (select 1 + count(t2.incidence) 
     from table t2 
     where t2.incidence > t.incidence 
     ) as rank 
from table t; 

變量的方法是有點棘手,因爲你要記住匹配的行數與給定值:

select t.*, 
     (@rn := if(@i = t.incidence, if(@cnt := @cnt + 1, @rn, @rn), 
        @cnt + if(@i := t.incidence, if(@cnt := 1, @rn, @rn), @rn) 
        ) 
     ) as rank 
    from table t cross join 
     (select @i := 0, @rn := 0, @cnt := 1) vars 
    order by incidence desc; 

編輯:

如果你想更新表格,只需用updatejoin

update table t join 
     (<either subquery above>) s 
     on t.id = s.id 
    set t.rank = s.rank; 
+0

這看起來比我的野蠻努力更清潔。不過,我並沒有在開場明確說明我需要更新表格。我想我可以寫一個新的,但更新會更受歡迎。 – 2014-12-19 02:42:33

+0

戈登 - 你可以用var示例填寫更新查詢嗎???你聲明「使用上面的子查詢」,但第二個有一個交叉連接,並且Im uncelar在那裏 - 我似乎可以找到其他引用... thx – jpmyob 2015-09-04 00:36:02