2015-04-30 37 views
4

我可能錯過了一些非常非常簡單的東西,但是我不能爲我的生活找出它是什麼,我沒有正確地做...MySQL CASE值範圍不起作用,但嵌套IF的呢?

我有這個查詢是用於抽出已完成志願工作的小時數,然後根據提交的小時數爲其分配獎勵。不難...

嵌套的IF解決方案是可怕的,只是一個後備,看看它是不是隻是搞亂了CASE。事實證明,Janky嵌套IF解決方案完美工作,因爲我的CASE解決方案仍然存在問題。

該查詢每年只運行一次以取消最終結果,因此性能並非真正的問題(嵌套的IF查詢當前執行時間爲0.0095秒/ 700行,這非常合適),它更多的是事實上,它完全令人討厭,我沒有工作,並想了解爲什麼以備將來參考。

作爲參考,小時值被存儲爲DECIMAL(8,2),隨後total_hours的值也是相同的類型。

我在尋找的輸出是:

| id | first_name | last_name | total_hours | award | 
|----|------------|------------|-------------|----------| 
| 1 | Bob  | Harrington | 0.50  | Silver | 
| 2 | Jim  | Halpert | 800.00  | Platinum | 
| 3 | Dwight  | Shrute  | 130.00  | Gold  | 
| 4 | Michael | Scott  | 5.00  | Bronze | 

CASE語句產生了具有「不到1個小時」爲award值的所有行,除非那些total_hours等於1.00,其中值爲award等於'青銅'。

根據上面的示例,嵌套的IF語句導致正確生成表。

這是我目前案件查詢,不工作:

SELECT 
    m.id, 
    m.first_name, 
    m.last_name, 
    total_hours, 
    CASE total_hours 
     WHEN total_hours >= 1 <= 50 THEN 
      'Bronze' 
     WHEN total_hours >= 51 <= 125 THEN 
      'Silver' 
     WHEN total_hours >= 126 <= 249 THEN 
      'Gold' 
     WHEN total_hours >= 250 THEN 
      'Platinum' 
     ELSE 
      'Less than 1 hour' 
    END AS award 
FROM (
    SELECT member_id, sum(hours) total_hours 
    FROM volunteering_hours 
    WHERE authorise_date > 0 AND validate_date > 0 AND delete_date = 0 
    GROUP BY member_id 
) hour_query 
LEFT JOIN members m ON m.id = member_id 
ORDER BY total_hours DESC 

我試過到目前爲止:

  • 配售原料比較數值加引號。
  • 給出比較數值小數位數。
  • 嘗試使用CASE語句只進行一次比較,就像測試一樣, WHEN total_hours > 1 THEN 'GT 1' ELSE 'LT 1' END award,所有列在運行查詢後仍然以LT 1出現 - 意味着它失敗。
  • 分組CASE語句
  • 更改每個範圍比較的語法total_hours >= 1 && total_hours <= 50,等等。它仍然得到同樣的結果失敗

我現在的嵌套IF解決方案,它看起來可怕,但至少是工作,是:

SELECT 
    m.id, 
    m.first_name, 
    m.last_name, 
    total_hours, 
    IF(total_hours >= 1 && total_hours <= 50, 'Bronze', 
     IF(total_hours >= 51 && total_hours <= 125, 'Silver', 
      IF(total_hours >= 126 && total_hours <= 249, 'Gold', 
       IF(total_hours >= 250, 'Platinum', 'Less than 1 hour') 
      ) 
     ) 
    ) award 
FROM (
    SELECT member_id, sum(hours) total_hours 
    FROM volunteering_hours 
    WHERE authorise_date > 0 AND validate_date > 0 AND delete_date = 0 
    GROUP BY member_id 
) hour_query 
LEFT JOIN members m ON m.id = member_id 
ORDER BY total_hours DESC 

有人可以請我淋浴一些知識,爲什麼CASE不工作?

在此先感謝。 :)

回答

3

你很近,但有一些語法錯誤。做到這一點,而不是:

CASE 
    WHEN total_hours >= 1 AND total_hours <= 50 THEN 
     'Bronze' 
    WHEN total_hours >= 51 AND total_hours <= 125 THEN 
     'Silver' 
    WHEN total_hours >= 126 AND total_hours <= 249 THEN 
     'Gold' 
    WHEN total_hours >= 250 THEN 
     'Platinum' 
    ELSE 
     'Less than 1 hour' 
END AS award 

Sample simplified SQL Fiddle

+0

謝謝!這是完美的,儘管@dognose提供瞭解釋,爲什麼,這有助於。所以我不確定哪一個標記爲答案,而不是詆譭你,它確實有幫助!爲此,我非常感謝。 :) – Othyn

+0

@Othyn樂意幫忙!選擇你覺得最好提供解決方案的答案。 – jpw

-1

請嘗試以下操作。

SELECT 
    m.id, 
    m.first_name, 
    m.last_name, 
    total_hours, 
    CASE WHEN total_hours between 1 and 50 THEN 
      'Bronze' 
     WHEN total_hours between 51 and 125 THEN 
      'Silver' 
     WHEN total_hours between 126 and 249 THEN 
      'Gold' 
     WHEN total_hours between 250 THEN 
      'Platinum' 
     ELSE 
      'Less than 1 hour' 
    END AS award 
FROM (
    SELECT member_id, sum(hours) total_hours 
    FROM volunteering_hours 
    WHERE authorise_date > 0 AND validate_date > 0 AND delete_date = 0 
    GROUP BY member_id 
) hour_query 
LEFT JOIN members m ON m.id = member_id 
ORDER BY total_hours DESC 

我不確定你是否可以在你的案例之間使用這樣的陳述,但我認爲你可以。如果你不能,那麼你只需要在案例陳述中正確分解,如total_hours >=1 and total_hours <=50

至於您的查詢,我會建議重組它像

select 
    m.id, 
    m.first_name, 
    m.last_name, 
    sum(vh.hours) total_hours, 
    case when sum(vh.hours) between 1 and 50 then 
      'bronze' 
     when sum(vh.hours) between 51 and 125 then 
      'silver' 
     when sum(vh.hours) between 126 and 249 then 
      'gold' 
     when sum(vh.hours) between 250 then 
      'platinum' 
     else 
      'less than 1 hour' 
    end as award 
from 
    volunteering_hours vh 

    left join members m on 
     m.id = member_id 
where 
    authorise_date > 0 and 
    validate_date > 0 and 
    delete_date = 0 
group by 
    vh.member_id, 
    m.id, 
    m.first_name, 
    m.last_name 
order by 
    total_hours desc 

嵌套表的東西都不是很大,你應該儘可能避免使用它們。有點乾淨,我認爲分組仍然可以正常工作。

2

你混合(不同的)情況下的語法。

如果使用case xx,那麼你時,不應再包含xx

case xx 
    when 1 then statement 
    when 2 then statement 

如果您只使用case那麼你可以需要提供變量進行比較:

case 
    when xx=1 then statement 
    when xx=2 then statement 

看到這裏的例子: http://sqlfiddle.com/#!9/d8348/6

與pr相比ogramming語言的第一個等於

switch(variable){ 
    case 1: statement; break; 
    case 2: statement; break; 
} 

,而第二個是

if (variable==1){ 
    statement; 
else if (variable==2){ 
    statement; 
} 
+0

謝謝! :)雖然我不確定是否標記你或者@jpw的答案作爲答案,因爲它們彼此都很有幫助! :) – Othyn