SQL查询四舍五入问题

问题描述 投票:0回答:2

我正在使用 pyodbc 根据一个叫做 "强度 "的标准来获取一个产品的总量。强度 "列对某些记录也有字符串值,所以它是一个 varchar 列。

用户输入品牌、产品类型、产品系列、日期范围、最小数量(本例中为12)和强度范围等详细信息。

这是我的查询。

SELECT SUM(CAST([Qty] AS decimal(10, 2))) AS Qty 
FROM (
    SELECT 
        [Brand], 
        [ProdType], 
        [Lot], 
        CAST([Strength] AS DECIMAL(10,4)) AS [Strength], 
        [ProductLine], 
        [Size], 
        [Stage], 
        [Customer], 
        [PackedOn], 
        [Qty], 
        [RefreshedBy], 
        [RefreshedOn] 
    FROM SalesData 
    WHERE 
        (isnumeric([Strength]) = 1) 
        AND [Stage]='WIP' 
        AND [PackedOn]>='2018-06-03' 
        AND [PackedOn]<='2020-06-03' 
        AND [Brand]='ABC' 
        AND [ProductLine]='DEF' 
        AND [Size]='15' 
        AND [Qty]>='12.0' 
        AND [Strength]>=0.2 
        AND [Strength]<=0.4 
        AND [ProdType] Is Null
) as outputdata

这是我的表

ID  Brand   ProdType    Lot   Strength  ProductLine   Size    Stage   Province  PackedOn    Qty  

1   ABC     NULL      XXXXXXX     0.16       DEF       15        WIP    NULL    2018-12-07  1200

这是我的表: This is the create statement

CREATE TABLE [dbo].[SalesData](
    [ID] [int] NOT NULL,
    [Brand] [varchar](max) NOT NULL,
    [ProdType] [varchar](max) NULL,
    [Lot] [varchar](max) NOT NULL,
    [Strength] [varchar](max) NOT NULL,
    [ProductLine] [varchar](max) NOT NULL,
    [Size] [varchar](max) NOT NULL,
    [Stage] [varchar](max) NOT NULL,
    [Province] [varchar](max) NULL,
    [PackedOn] [date] NOT NULL,
    [Qty] [float] NOT NULL,
    [RefreshedBy] [varchar](max) NULL,
    [RefreshedOn] [varchar](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

我的问题是,这个查询的结果是数量为1200,尽管它超出了强度范围。我使用的是SQL Server Management Studio V 18.4。我如何解决这个问题?

python sql sql-server pyodbc
2个回答
2
投票

在你的WHERE子句中,你应该使用。

TRY_CAST([Strength] AS DECIMAL(10,4))>=0.2 AND TRY_CAST([Strength] AS DECIMAL(10,4))<=0.4

因为sql查询是从where子句(和join)开始工作的,然后执行其他部分。SELECT 是最不重要的部分,如果你只使用 CAST 在您的选择中,它只对打印数据作为您的首选格式有用。

SELECT SUM(CAST([Qty] AS decimal(10, 2))) AS Qty FROM 
(SELECT [Brand], [ProdType], [Lot], CAST([Strength] AS DECIMAL(10,4)) AS [Strength], [ProductLine], [Size], [Stage], [Customer], [PackedOn], [Qty], [RefreshedBy], [RefreshedOn] 
FROM SalesData 
WHERE (isnumeric([Strength]) = 1) AND [Stage]='WIP' AND [PackedOn]>='2018-06-03' 
AND [PackedOn]<='2020-06-03' AND [Brand]='ABC' AND [ProductLine]='DEF' 
AND [Size]='15' AND [Qty]>='12.0' AND TRY_CAST([Strength] AS DECIMAL(10,4))>=0.2 AND TRY_CAST([Strength] AS DECIMAL(10,4))<=0.4 AND [ProdType] Is Null) as outputdata

1
投票

您需要 CAST() 在做数字比较之前,否则SQL Server比较的是字符串,而不是数字,这会导致意外的结果:举个例子,字符串方面。'2' 大于 '12' (因为它是以 '2'大于 '1') 这对查询中涉及的所有数字比较都是如此 (Size 也是有关)。)

我建议 TRY_CAST(),它避免了错误,并返回 null 如果转换失败(这将有效地使条件失败,并从查询中删除相应的记录)。

另外,子查询也是不必要的。

考虑一下。

SELECT SUM(Qty) Qty
FROM SalesData 
WHERE 
    Stage = 'WIP' 
    AND PackedOn >= '2018-06-03' 
    AND PackedOn <= '2020-06-03' 
    AND Brand = 'ABC' 
    AND ProductLine = 'DEF' 
    AND ProdType Is Null
    AND Qty >= 12
    AND TRY_CAST(Strength AS DECIMAL(10, 4)) >= 0.2
    AND TRY_CAST(Strength AS DECIMAL(10, 4)) <= 0.4 
    AND TRY_CAST(Size AS INT) = 15

如果你想把你的 float 输出到 decimal,更准确的说法是,这之后的 sum()所以..:

SELECT CAST(SUM(Qty) AS DECIMAL(10, 2)) Qty
FROM ...
© www.soinside.com 2019 - 2024. All rights reserved.