2012-07-12 43 views
2

我試圖將CASE語句中的值組合在SQL Server中。當這些值是正值時,它工作正常。當這些值是負值時,它會爆炸。在SQL Server CASE中對負值進行分組

Here's a link to the SQL Fiddle I created to replicate it:

下面是代碼:

-- Create the table -- 

    CREATE TABLE Test (
     ClientID varchar(12), 
     Value decimal(12,10) 
     PRIMARY KEY (ClientID) 
    ); 


    -- Load the data -- 
    INSERT INTO Test (ClientId, Value) 
      VALUES('1','10'), 
      ('2','-10'), 
      ('3','11.2'), 
      ('4','-11.6'), 
      ('5','12.544'), 
      ('6','-13.456'), 
      ('7','14.04928'), 
      ('8','-15.6089'), 
      ('9','15.7351'), 
      ('10','-18.1063'), 
      ('11','17.6234'), 
      ('12','-21.0034'), 
      ('13','19.7382'), 
      ('14','-24.3639'), 
      ('15','22.1068'), 
      ('16','-28.2621'), 
      ('17','24.7596'), 
      ('18','-32.7841'), 
      ('19','27.7307'), 
      ('20','-38.0296'), 
      ('21','31.0584'), 
      ('22','-44.1141'), 
      ('23','34.785499'), 
      ('24','-51.1726'), 
      ('25','38.9597'), 
      ('26','-59.3602'), 
      ('27','43.6349'), 
      ('28','-68.8579'), 
      ('29','48.8711'), 
      ('30','-79.8751'); 

現在運行CASE聲明:

SELECT 
    CASE 
    WHEN Value BETWEEN 0 AND 20 THEN '0-20' 
    WHEN Value BETWEEN 21 AND 40 THEN '20-40' 
    ELSE '40+' 
    END as ValueRange, count(*) as count 
FROM Test 
WHERE Value > 0 
GROUP BY CASE 
    WHEN Value BETWEEN 0 AND 20 THEN '0-20' 
    WHEN Value BETWEEN 21 AND 40 THEN '20-40' 
    ELSE '40+' 
    END 
; 

這工作正常。結果:

VALUERANGE  count 
0-20   7 
20-40   6 
40+   2 

現在負值 - 這是行不通的:

SELECT 
    CASE 
    WHEN Value BETWEEN 0 AND -20 THEN '0-20' 
    WHEN Value BETWEEN -21 AND -40 THEN '20-40' 
    ELSE '40+' 
    END 
as ValueRange, count(*) as count 
FROM Test 
WHERE Value < 0 
GROUP BY CASE 
    WHEN Value BETWEEN 0 AND -20 THEN '0-20' 
    WHEN Value BETWEEN -21 AND -40 THEN '20-40' 
    ELSE '40+' 
    END 
; 

結果:

VALUERANGE count 
40+   15 

這一切都很組爲40+ - 不打破低valueranges。

任何人都可以看到我做錯了什麼?

+1

「爆炸」和「不起作用」是什麼意思?您的第二個查詢明確排除了「WHERE」條款中的負數。 – Pondlife 2012-07-12 22:45:10

+0

你是對的 - 更新查詢。即使這樣,我也沒有得到我期待的結果。 – mikebmassey 2012-07-12 22:46:20

回答

3

嘗試

SELECT 
    CASE 
    WHEN Value BETWEEN -20 AND 0 THEN '0-20' 
    WHEN Value BETWEEN -40 AND -21 THEN '20-40' 
ELSE '40+' 
END 
as ValueRange, count(*) 
FROM Test 
--WHERE Value > 0 
GROUP BY CASE 
    WHEN Value BETWEEN -20 AND 0 THEN '0-20' 
    WHEN Value BETWEEN -40 AND -21 THEN '20-40' 
    ELSE '40+' 
END 
; 

我期望之間的第一爲最小值。

ValueRange 
---------- ----------- 
0-20  5 
20-40  5 
40+  20 
+1

這是正確的,你也可能希望那裏的條件回到那裏,但它應該讀'WHERE Value <0' http://sqlfiddle.com/#!3/e023a/9/0 – Ghost 2012-07-12 22:44:14

+0

謝謝。這讓它爲我工作。 – mikebmassey 2012-07-12 22:52:43

+1

這就是我寧願使用> = ...和<(或<=)之間的原因之一。英文意思不符合tsql的含義。 – automatic 2012-07-12 22:55:14

3

你的問題已經解決了(先放負值,這樣的值之間按升序排列),但你可能會喜歡看一些可替代的查詢語法(這是我喜歡CASE結構就像你有):

SELECT 
    ValueRange = 
     Convert(varchar(11), R.Low) 
     + Coalesce(' - ' + Convert(varchar(11), R.High - 1), '+'), 
    Qty = Count(*) 
FROM 
    dbo.Test T 
    INNER JOIN (
     SELECT 0, 21 
     UNION ALL SELECT 21, 41 
     UNION ALL SELECT 41, NULL 
    ) R (Low, High) 
     ON T.Value >= R.Low 
     AND T.Value < Coalesce(R.High, 2147483647) 
WHERE T.Value >= 0 
GROUP BY R.Low, R.High; 

我更喜歡這個,因爲我發現修改範圍值比使用case語句更容易,再加上它有助於避免在文本描述中重複數字。

如果你只是想在每塊20,那麼這是比較容易:

SELECT 
    BlockHigh = (Value + 19)/20 * 20, -- 20 for 1-20, 40 for 21 - 40, etc. 
    Qty = Count(*) 
FROM dbo.Test 
GROUP BY (Value + 19)/20 * 20; 

我假設,你可能不使用整數來的第一個查詢,並在你的第二個查詢。

請注意,您的「40+」是錯誤的,因爲它與您編寫CASE聲明的方式確實是「41+」。

+0

+1我也找到了這個清潔工。 – 2012-07-12 23:35:13

相關問題