2014-06-11 40 views
1

爲了最終確定我今天的MySQL問題,我想就此問題提出一些建議。我有一張表,我需要添加一個計算值的列。我不想更新表格 - 只是結合信息。 我正在使用的表看起來像這樣:在MySQL中循環返回錯誤值時的情況

 +----------------+----------------+--------------------------------------+ 
     | VOTE_CANDIDATE | ORIGINAL_VOTES | SURPLUS_REDISTRIBUTION_TO_CANDIDATES | 
     +----------------+----------------+--------------------------------------+ 
     |    1 |    8 |         -1 | 
     |    2 |    1 |         -1 | 
     |    3 |    2 |         -1 | 
     |    4 |    4 |         -1 | 
     |    5 |    2 |         -1 | 
     |    6 |    3 |         -1 | 
     +----------------+----------------+--------------------------------------+ 

我的問題是,只有第1行應返回-1列SURPLUS_REDISTRIBUTION_TO_CANDIDATES因爲它是ORIGINAL_VOTES大於7的閾值時,剩下的應該(如低於狀態的情況)由於低於閾值而返回零。看起來,查詢鎖定在第一行,然後在所有行上重新使用SURPLUS_REDISTRIBUTION_TO_CANDIDATES。這是我正在處理的查詢:

SELECT vote_candidate, COUNT(*) original_votes, CASE 
    WHEN (
    (
     SELECT MAX(
     (
      SELECT COUNT(*) votes_above_the_threshold 
      FROM vote_orders 
     ) 
    ) votes 
     FROM vote_orders 
     WHERE vote_order = 1 
    ) >= (
     SELECT FLOOR((COUNT(*)/(2 + 1)) + 1) threshold 
     FROM votes 
    ) 
) 
    THEN (
    SELECT FLOOR((COUNT(*)/(2 + 1)) + 1) threshold 
    FROM votes 
) - (
    SELECT MAX(votes_above_the_threshold) votes 
    FROM (
     SELECT vote_candidate vote_candidate, COUNT(*) votes_above_the_threshold 
     FROM vote_orders 
     WHERE vote_order = 1 
     GROUP BY vote_candidate 
     HAVING votes_above_the_threshold >= (
     SELECT FLOOR((COUNT(*)/(2 + 1)) + 1) threshold 
     FROM votes 
    ) 
    ) t 
    WHERE votes_above_the_threshold = (
     SELECT MAX(votes_above_the_threshold) 
     FROM vote_orders 
    ) 
) 
    ELSE 0 
END surplus_redistribution_to_candidates 
FROM vote_orders 
WHERE vote_order = 1 
GROUP BY vote_candidate; 

如何獲得我要查找的結果?

回答

1

我很難破譯你的查詢做什麼,以及爲什麼它正在做它做的事情。

它看起來像有一個「門檻」;這是根據針對votes表的查詢中的表達式計算的。

如果目標是回到了「門檻」值和每個候選的「orginal_votes」值之間的非積極的變化,我會做這樣的:

SELECT c.vote_candidate 
    , c.original_votes 
    , LEAST(0,t.threshold - c.original_votes) AS surplus_redistribution_to_candidates 
    FROM (SELECT o.vote_candidate 
       , COUNT(*) original_votes 
      FROM vote_orders o 
      WHERE o.vote_order = 1 
      GROUP 
      BY o.vote_candidate 
     ) c 
CROSS 
    JOIN (SELECT FLOOR((COUNT(*)/(2 + 1)) + 1) AS threshold 
      FROM votes 
     ) t 
ORDER BY c.vote_candidate 

內聯視圖別名爲c獲得每個候選人的「original_votes」,而內聯視圖別名爲「t」獲得「閾值」。外部查詢比較兩個值,並返回差值(如果爲負值)或零。


我不認爲你的查詢鎖定到第一行。相反,我認爲問題是每SELECT MAX()子查詢的每次執行都會返回相同的值,每個vote_candidate。而恰巧巧合的是,最大值碰巧與結果集中的「第一個」vote_candidate相關聯。

看起來您只是想比較每個vote_candidate的「original_votes」與「閾值」值。看起來好像所有這些子查詢都是完全不必要的;他們只是造成混亂。與此

LEAST(0,t.threshold - c.original_votes) 


如果你想避免使用MySQL LEAST()功能,並使用ANSI標準CASE表達,那麼你可以

替換此

CASE 
    WHEN t.threshold < c.original_votes 
    THEN t.threshold - c.original_votes 
    ELSE 0 
    END 
+0

很棒的回答。它不僅工作 - 你也爲我澄清事情。我必須承認 - 這個片段所屬的整個查詢更加令人困惑。這個解決方案雖然對此有所闡述。 :) 非常感謝你!向上投票並標記爲答案。 –

+0

如果整個查詢與此片段一樣令人困惑,則可能需要重新考慮整個查詢的方法,特別是如果您的查詢包含子查詢,尤其是如果它多次重複相同的子查詢。我懷疑有一個更簡單(更容易理解)的方法來解決這個問題。 – spencer7593