【问题标题】:How can I use Sum, Cast and Partition by functions together?如何同时使用 Sum、Cast 和 Partition by 函数?
【发布时间】:2019-03-03 05:36:57
【问题描述】:

如何同时使用 Sum、Cast 和 Partition by 函数?

我得到错误。

将 nvarchar 值“693.41”转换为数据时转换失败 输入整数。”

我试过了

SUM(CAST([total price] AS INT)) OVER (PARTITION BY (ProjectType)) as TotalPriceV2

完整查询如下。

SELECT 
    ID,
    [Project Manager], 
    Job#, 
    [Date], 
    [Job Type],
    first_value([Job Name]) OVER (PARTITION BY value_partition ORDER BY ID) CustomerGroup, Value_Partition 
    Customer,
    [Sales Rep1],
    DeliveryType,
    ProjectType,
    [Item Price],
    [Service Price],
    [Total Price],
    SUM(CAST([total price] AS INT)) OVER (PARTITION BY (ProjectType)) as TotalPriceV2
FROM (
    SELECT 
    ID,
    [Project Manager], Job#, [Date], [Job Type], [Job Name],Customer,[Sales Rep1],DeliveryType,ProjectType,[Item Price],[Service Price],[Total Price],
    SUM(CASE WHEN [JOB NAME] IS NULL THEN 0 ELSE 1 END) OVER (ORDER BY ID) AS Value_Partition   
    FROM Testing2
    WHERE 
    [Date] IS NOT NULL AND 
    ([Date]  NOT LIKE '0' OR JOB# NOT LIKE '0' OR [JOB TYPE] NOT LIKE '0')
    AND [Project Manager] NOT LIKE 'ITEM / SERVICE'
) AS X

【问题讨论】:

  • 为什么total price是一个字符类型?而不是DECIMAL/NUMERIC?另外,你为什么要投射到INT,这会删除小数点?

标签: sql sql-server ssms


【解决方案1】:

首先,找出有问题的行。您正在转换为int,所以:

select price
from Testing2
where try_convert(int, price) is null and price is not null;

至少一些值会有小数点(如您的示例中所示)。要查看这是否是唯一的问题,我建议接下来转换为小数:

select price
from Testing2
where try_convert(decimal(20, 4), price) is null and price is not null;

如果这不返回任何内容,则说明您已设置。如果没有,您将需要弄清楚如何解决这些异常。

然后,我将使用 decimals 而不是浮点数来表达计算:

SUM(TRY_CAST([total price] AS DECIMAL(20, 4))) OVER (PARTITION BY (ProjectType)) as TotalPriceV2

货币金额通常应使用定点值而不是近似浮点值来表示。浮点值的问题是信息可能会丢失。以reals 为例:

select cast(1000000 as real) + cast(0.01 as real),
       cast(1000000 as decimal(20, 4)) + cast(0.01 as decimal(20, 4))

【讨论】:

  • @gordon_linoff,谢谢这个 ('SUM(TRY_CAST([total price] AS DECIMAL(20, 4))) OVER (PARTITION BY (ProjectType)) as TotalPriceV2') 工作正常。跨度>
【解决方案2】:

整数没有十进制值,它会抛出错误。

如果我使用它,类似于您的示例。

Declare @val nvarchar(10) = '10.24' 

select   cast (@val as int) 

我收到以下错误。

Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the nvarchar value '10.24' to data type int.

现在为了避免这个错误,我可以将数字四舍五入到小数点后 0 位并转换为 Int。另外,如果您使用的是 sql server 2012 或更高版本,我建议使用 Try_Cast 来避免任何实际 nvarchar 值的情况(它会将其转换为 null)。

 Declare @val nvarchar(10) = '10.24' 

select   Try_cast (round(@val,0) as int)   as valuen

输出,我认为这将在您的 sum 函数中起作用。

valuen
10

【讨论】:

  • ROUND 会自动转换为某种形式的十进制,因此您不需要使用CAST/TRY_CAST`。
  • @Clockwork-Muse 感谢您的反馈,这是有道理的!
【解决方案3】:

你为什么不用十进制(16,9)而不是int在内部查询中转换它

SELECT 
    ID,
    [Project Manager], 
    Job#, 
    [Date], 
    [Job Type],
    first_value([Job Name]) OVER (PARTITION BY value_partition ORDER BY ID) CustomerGroup, Value_Partition 
    Customer,
    [Sales Rep1],
    DeliveryType,
    ProjectType,
    [Item Price],
    [Service Price],
    [Total Price],
    SUM([total price]) OVER (PARTITION BY (ProjectType)) as TotalPriceV2
FROM (
    SELECT 
    ID,
    [Project Manager], Job#, [Date], [Job Type], [Job Name],Customer,[Sales Rep1],DeliveryType,ProjectType,[Item Price],[Service Price],cast([Total Price] as decimal(16,9)) as [Total Price],
    SUM(CASE WHEN [JOB NAME] IS NULL THEN 0 ELSE 1 END) OVER (ORDER BY ID) AS Value_Partition   
    FROM Testing2
    WHERE 
    [Date] IS NOT NULL AND 
    ([Date]  NOT LIKE '0' OR JOB# NOT LIKE '0' OR [JOB TYPE] NOT LIKE '0')
    AND [Project Manager] NOT LIKE 'ITEM / SERVICE'
) AS X

【讨论】:

  • "casting inside" 不是您所做的重要更改 - 它将目标转换类型更改为 DECIMAL。您可以将演员表留在外部查询中,它会起作用。
【解决方案4】:

如果您将字符串和数字组合作为列值,并且您想对数字求和。对于SQL Server 2012+,您可以使用TRY_CASTTRY_CONVERT 来避免任何转换错误。

TRY_CAST (Transact-SQL)

在您的场景中,您没有使用正确的数据类型进行转换,您的值如 693.41 不能转换为 INT,而您应该使用 DECIMAL 数据类型。

还有一个建议,不要使用NOT LIKE,最好在SQL Server 中使用<>,如下所示。

改变

 ([Date]  NOT LIKE '0' OR JOB# NOT LIKE '0' OR [JOB TYPE] NOT LIKE '0')

 ([Date] <> '0' OR JOB# <> '0' OR [JOB TYPE] <> '0')

【讨论】:

  • TRY_CAST 会默默吞下错误,这是错误的做法。
  • @Clockwork-Muse,你是对的,我会在答案中提到。
  • @PSK "TRY_CAST (Transact-SQL)" 返回 NULL 值
【解决方案5】:

一种可能的解决方案是先将 nvarchar 值转换为十进制,然后再转换为整数:

CAST(CAST([total price] AS FLOAT) AS INT)

但是,如果对您很重要,这样小数部分就会丢失。

【讨论】:

  • 如果我能得到小数那就太好了,但这很好用。谢谢你的回答@rad
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多