我正在尝试将CASE
语句中的值组合在一起SQL Server
。当值为正时,它可以正常工作。当值为负时,它会爆炸。
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+ - 不分解较低的值范围。
谁能看到我做错了什么?
答案 0 :(得分: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 :(得分:3)
你的问题已经解决了(把负数放在首位,所以BETWEEN值按升序排列)但你可能希望看到一些替代查询语法(我更喜欢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+”。