我正在使用 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。我如何解决这个问题?
在你的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
您需要 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 ...