Rod*_*y G 11 sql-server datatypes t-sql type-conversion
我遇到了一个问题,即CASE表达式没有返回我期望的内容。
作为测试,我添加了一个十进制变量并CASE针对它运行了相同的表达式,它运行良好,返回了我预期的结果(在 时将值向上舍入IsGun=1。但是当我CASE针对另一个十进制值运行相同的表达式时,它总是返回CEILING()函数的值,从不返回原始值。
这是SQL代码:
DECLARE @Num decimal(8,2);
set @Num = 12.54;
WITH PQ AS
(
SELECT
UPC,
Price1,
DBID,
AVG(Price1) OVER (PARTITION BY UPC) AS Price1Avg
FROM
vProducts_PriceQty_Union
)
SELECT
PQ.UPC,
PQ.Price1,
PQ.Price1Avg,
(CASE WHEN p.IsGun = 1 THEN CEILING(@Num) ELSE @Num END) AS UsingVar,
CAST(
(CASE WHEN P.IsGun = 1 THEN CEILING(PQ.Price1Avg) ELSE PQ.Price1 END)
AS NUMERIC(8,2))
AS PriceAdj,
PQ.DBID,
P.IsGun
FROM
PQ
INNER JOIN
products P ON PQ.UPC = P.UPC
Run Code Online (Sandbox Code Playgroud)
这是结果的一个片段:
DECLARE @Num decimal(8,2);
set @Num = 12.54;
WITH PQ AS
(
SELECT
UPC,
Price1,
DBID,
AVG(Price1) OVER (PARTITION BY UPC) AS Price1Avg
FROM
vProducts_PriceQty_Union
)
SELECT
PQ.UPC,
PQ.Price1,
PQ.Price1Avg,
(CASE WHEN p.IsGun = 1 THEN CEILING(@Num) ELSE @Num END) AS UsingVar,
CAST(
(CASE WHEN P.IsGun = 1 THEN CEILING(PQ.Price1Avg) ELSE PQ.Price1 END)
AS NUMERIC(8,2))
AS PriceAdj,
PQ.DBID,
P.IsGun
FROM
PQ
INNER JOIN
products P ON PQ.UPC = P.UPC
Run Code Online (Sandbox Code Playgroud)
这是它来自vProducts_PriceQty_Union的数据:
UPC Price1 Price1Avg UsingVar PriceAdj DBID IsGun
942000899195 14.9900 14.990000 12.54 15.00 1 0
980420671300 29.9900 29.990000 12.54 30.00 1 0
980420671310 29.9900 29.990000 12.54 30.00 1 0
980426713020 29.9900 29.990000 12.54 30.00 1 0
980426713120 29.9900 29.990000 12.54 30.00 1 0
000998622130 319.0000 319.000000 13.00 319.00 1 1
000998624730 314.0000 314.000000 13.00 314.00 1 1
000998624970 419.0000 419.000000 13.00 419.00 1 1
008244284754 1015.0000 1015.000000 13.00 1015.00 2 1
010633012288 267.0000 267.000000 13.00 267.00 6 1
Run Code Online (Sandbox Code Playgroud)
从前五个表达式中可以看出,其中IsGun = 0,CASE使用固定变量的第一个表达式返回UsingVar值,正如我们所期望的那样,12.54。对于最后五个,它也返回我们期望的值,13。
但是在第二个CASE表达式中(完全相同的逻辑),PriceAdjCEILING对它们中的每一个都使用该函数,无论IsGun = 1 与否。
为什么查询没有返回预期的结果?
在一些用于联合的表的视图的数据类型价格1和Price2分别SMALLMONEY和十进制(8,2) 。我已经将它们全部更改为decimal(8,2),但这并没有影响结果。
Dan*_*her 11
要重现问题:
SELECT *, (CASE
WHEN IsGun=1 THEN CEILING(Price1Avg)
ELSE Price1 END)
FROM (
SELECT UPC, IsGun, Price1,
AVG(CAST(Price1 AS numeric(8, 2))) OVER (PARTITION BY UPC) AS Price1Avg
FROM (
VALUES ('A', 0, 14.99),
('B', 0, 29.99),
('C', 1, 319.00),
('D', 1, 314.00)
) AS x(UPC, IsGun, Price1)
) AS sub;
Run Code Online (Sandbox Code Playgroud)
这里发生的是CEILING(PQ.Price1Avg)产生一个numeric(38, 0).
根据文档,输出类型CEILING()与输入具有相同的基本数据类型,尽管比例(小数位数)可能会发生变化,这就是这里发生的情况。
AVG()在我的测试中,该函数返回numeric(38, 6).CEILING()但是,该列上的函数输出numeric(38, 0):验证:
SELECT CEILING(CAST(123.45 AS numeric(38, 6)))
Run Code Online (Sandbox Code Playgroud)
作为一种解决方法,您可以显式转换CEILING()函数的输出,这应该会给您正确的结果:
SELECT *, (CASE
WHEN IsGun=1 THEN CAST(CEILING(Price1Avg) AS numeric(8, 2)) -- Explicit CAST.
ELSE Price1 END)
FROM (
SELECT UPC, IsGun, Price1,
AVG(CAST(Price1 AS numeric(8, 2))) OVER (PARTITION BY UPC) AS Price1Avg
FROM (
VALUES ('A', 0, 14.99),
('B', 0, 29.99),
('C', 1, 319.00),
('D', 1, 314.00)
) AS x(UPC, IsGun, Price1)
) AS sub;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1925 次 |
| 最近记录: |