2014-04-17 94 views
1

我使用MariaDB(根據我的有限概念,MySQL的一個簡單替換)來支持一個小小的選舉應用程序。SQL:計算(並填充?)排序結果之間的差異

我與候選人存儲的東西之一就是「首領」 - 即他們的多少是多少。如果候選人A獲得6票,候選人B獲勝12,候選人C獲勝7,則值爲0,5,0。

但是現在我有了一個很大的新數據集,在那裏我知道成績和選票,但對「leadingmargin」沒有任何意義。有數百名候選人,所以我需要計算這個。這就是我的意思是用英語來做:

  1. 按騎行排序每個人。
  2. 然後按票數排序。
  3. 減去(排名第一的候選人的票數 - 排名第二的候選人的票數)並將結果存儲在排名第一的「領先優勢」列中。
  4. 其他人都得到一個0.或者讓它保持NULL。

下面是一個完整的表格來顯示我要去的例子。它和真實數據唯一的區別是我沒有計算出「領先指數」。

MariaDB [databasename]> SELECT * FROM `demo_candidates` ORDER BY `riding` ASC , `votes` DESC; 
+--------+-----------+-----------+---------+-------+-------+---------------+---------+ 
| id  | riding | lname  | fname | party | votes | leadingmargin | percent | 
+--------+-----------+-----------+---------+-------+-------+---------------+---------+ 
|  1 |   1 | Redford | Richard |  1 | 92 |   50 | 57.14 | 
|  4 |   1 | Pelford | Paul |  4 | 42 |    0 | 26.09 | 
|  3 |   1 | Yeltmate | Yoris |  3 | 16 |    0 | 9.94 | 
|  2 |   1 | Gint  | Ginny |  2 | 11 |    0 | 6.83 | 
|  6 |   2 | Gelford | Gippy |  2 | 99 |   16 | 44.59 | 
|  5 |   2 | Roberts | Roy  |  1 | 83 |    0 | 37.39 | 
|  8 |   2 | Peg  | Porkay |  4 | 28 |    0 | 12.61 | 
|  7 |   2 | Yavin  | Yordy |  3 | 12 |    0 | 5.41 | 
etc.. 
+--------+-----------+-----------+---------+-------+-------+---------------+---------+ 
20 rows in set (0.00 sec) 
+1

這是遊標或者用於對數據做後期處理的應用程序的工作。你可以在純SQL中做到嗎?幾乎肯定。它會很漂亮和/或表演嗎?幾乎肯定不是。另外,如果您更新某行以更改給定行的投票列的值,則leadingmargin列將不再準確,並且必須再次更新。換句話說,當您使用顯示值(例如,在viewmodel類中)時,leadingmargin可能是您應該在運行時計算的值。 – dodexahedron

+0

這是一個非常好的觀點 - 對我來說這不是問題,因爲結果是「在罐子裏」,並且不會改變(除非法庭判決有爭議)。但是,是的,我可以更輕鬆地在PHP中執行此操作。我將在未來做到這一點,或者如果這成爲一個風聲草。 –

+0

如果mySQL支持它們,將你的數據子集放入一個表變量(基本上是內存中的表),或者甚至是一個臨時表都可以顯着提高性能,如果這是一個問題。 –

回答

1

此查詢僅設置獲獎者的領先優惠。如果您對leadingmargin由默認值設定爲0,或運行其他查詢設置那些0,你會好:

UPDATE demo_candidates t1 
LEFT JOIN demo_candidates t2 
    ON t2.riding = t1.riding 
    AND t2.votes > t1.votes 
JOIN demo_candidates t3 
    ON t3.riding = t1.riding 
    AND t3.votes < t1.votes 
LEFT JOIN demo_candidates t4 
    ON t4.riding = t3.riding 
    AND t4.id <> t1.id 
    AND t4.votes > t3.votes 
SET t1.leadingmargin = t1.votes - t3.votes 
WHERE t2.id IS NULL AND t4.id IS NULL 

如果是贏家領帶或只有一個人選,leadingmargin將不會被設置。

UPDATE:

這一個設置0太:

UPDATE demo_candidates t1 
LEFT JOIN demo_candidates t2 
    ON t2.riding = t1.riding 
    AND t2.votes > t1.votes 
LEFT JOIN demo_candidates t3 
    ON t3.riding = t1.riding 
    AND t3.votes < t1.votes 
LEFT JOIN demo_candidates t4 
    ON t4.riding = t3.riding 
    AND t4.id <> t1.id 
    AND t4.votes > t3.votes 
SET t1.leadingmargin = IF(t2.id IS NULL AND t4.id IS NULL, t1.votes - t3.votes, 0) 
+0

在主要選舉中,關係和鼓掌非常罕見,只需手動處理這些情況就簡單多了。那麼,除非我有一個處理數千次選舉的應用程序。但這主要只是我自己的學術練習。 如果有四個以上的候選人,這是否可以工作?無論如何,我有兩個有五個候選人,而且恰好工作。 –

+0

@WillMatheson,看我的更新。是的,它適用於任何數量的候選人(> 1)。 –