我有以下t-sql查询。
DECLARE @Test TABLE(
Points INT
,PointsOf INT
)
INSERT INTO @Test
VALUES (3,12),(2,12),(3,12),(11,12),(12,12),(5,12),(0,12)
DECLARE @Decimal TINYINT = 2
SELECT
CASE @Decimal
WHEN 0 THEN CAST(CAST(SUM(Points) AS DECIMAL(18,0)) / NULLIF(SUM(PointsOf), 0) * 100 AS DECIMAL(18,0))
WHEN 1 THEN CAST(CAST(SUM(Points) AS DECIMAL(18,1)) / NULLIF(SUM(PointsOf), 0) * 100 AS DECIMAL(18,1))
WHEN 2 THEN CAST(CAST(SUM(Points) AS DECIMAL(18,2)) / NULLIF(SUM(PointsOf), 0) * 100 AS DECIMAL(18,2))
END AS Score
FROM @Test
我有一个变量@Decimals
。当变量为0时,我需要我的查询以XX格式返回分数,当它的XX.X格式为1时,以及XX.XX格式的2时。
这里发生的是CASE输入多个THEN子句。当执行上面的查询时,我得到44.86作为结果是正确的,但是当我将@Decimals
valiable更改为0时,我得到结果44.00,这是incorect。它假设只返回44而没有小数。同样的事情发生在@Decimals
为1时,当它必须为44.9时返回44.90。
有人知道为什么会这样吗?
答案 0 :(得分:4)
我不知道MS Server是如何工作的,但是根据ANSI SQL规范,列总是有一个特定的数据类型,在这种情况下是十进制(20,2),即可以存储的最小数据类型所有案例的结果类型都不同。
答案 1 :(得分:4)
正如jarlh非常正确地指出case语句将其转换为可能的最小数据类型以保存所有结果类型。 (参见MSDN documentation,特别是返回类型部分)
从我的观点来看,这只是一个显示问题。当44.9
变量设置为1时,您希望显示44.90
而不是@decimal
(请注意尾随零)。
执行此操作的一种方法是向varchar添加其他强制转换。它不漂亮,不是我建议做的事情,但如果你坚持在SQL Server中做格式化和UI类型的事情,那么你能做什么?
DECLARE @Test TABLE(
Points INT
,PointsOf INT
)
INSERT INTO @Test
VALUES (3,12),(2,12),(3,12),(11,12),(12,12),(5,12),(0,12)
DECLARE @Decimal TINYINT = 1
SELECT
CASE @Decimal
WHEN 0 THEN cast(Cast(CAST(SUM(Points) AS DECIMAL(18,0)) / NULLIF(SUM(PointsOf), 0) * 100 as decimal(18,0)) as varchar(10))
WHEN 1 THEN cast(Cast(CAST(SUM(Points) AS DECIMAL(18,1)) / NULLIF(SUM(PointsOf), 0) * 100 as decimal(18,1))as varchar(10))
WHEN 2 THEN cast(Cast(CAST(SUM(Points) AS DECIMAL(18,2)) / NULLIF(SUM(PointsOf), 0) * 100 as decimal(18,2))as varchar(10))
END AS Score
FROM @Test