[英]Fixing an SQL where statement that is ugly and confusing
我直接查询后端MS SQL Server的软件包。 虽然我们在字段中输入数值,但关键字段(车辆编号)被定义为alpha。 这只有一个例外,我们在车辆退役时在号码前加上“R”(这意味着我们卖掉它或者车辆被废弃)。 假设用户这样做,我们不应该使用此方法遇到问题。 (对或错不是问题)
快进到现在。 我正在尝试查询这些车辆编号的子集(800 - 899)以进行一些特殊处理。 通过做'800'到'899'的范围,我们也得到80,81等。如果我将车辆编号投入INT,我应该能够获得正确的范围。 除了这些“R”车辆现在踢我的屁股。
我已经尝试过where vehicleId not like 'R%' and cast(vehicleId as int) between 800 and 899
但是,我在其中一辆“R”车辆上出现了投射错误。
什么工作是where vehicleId not between '800' and '899' and cast(vehicleId as int) between 800 and 899'
,但我觉得必须有更好的方式和更少混乱的方式。
我还尝试了HAVING
和子查询的其他变体都产生了投射错误。
虽然未经测试,但这应该可以解决问题:
where cast(replace(vehicleId,'R','') as int) between 800 and 899
使用_
运算符而不是%
运算符:
WHERE vehicleId LIKE 'R8__' OR vehicleId LIKE '8__'
您也可以将它们组合起来:
WHERE vehicleId LIKE '%8__'
无法保证优化器将以正确的顺序执行这些(当前SQL中没有短路评估):
where vehicleId not like 'R%' and cast(vehicleId as int) between 800 and 899
演员阵容可能会失败。
尝试这个:
WHERE
CASE
WHEN vehicleId NOT LIKE 'R%' THEN
CAST(vehicleId as int)
ELSE
0
END BETWEEN 800 AND 899
这个怎么样:
WHERE vehicleId BETWEEN '800' and '899' AND LEN(vehicleId) = 3
不是很干净,但它会消除两个角色的匹配。
好吧你的问题是你正在尝试对字符串字段进行数学排序。
尝试使用派生表来首先排除非数字和tehn将结果数据转换为int
select * from
(select * from mytable where vehicleId not like 'R%')a
where cast(vehicleId as int) between 800 and 900
好吧,这不起作用,你可以尝试select * from(select * from mytable where isnumeric(vehicleId)= 0)a cast(vehicleId as int)在800和900之间
isnumeric存在一些问题,但是如果它有效,你可以编写一个isint()函数并使用它。
where 1=
(
case
when
vehicleId like 'R%' then 0
else
(case when cast(vehicleId as int) between 800 and 899 then 1 else 0 end)
end
)
我不确定您是否希望包含'R%'记录以及vehicleIds的范围是否可变,但这可能会有所帮助。
WHERE vehicleId LIKE '8[0-9][0-9]'
OR vehicleId LIKE 'R8[0-9][0-9]'
如果范围是变量,那么你可能想要这样的东西。
WHERE CASE WHEN vehicleId LIKE 'R%' THEN CAST(SUBSTRING(vehicleId,2,99) AS INT)
WHEN vehicleId LIKE '[0-9][0-9][0-9]' THEN CAST(vehicleId AS INT)
END BETWEEN 800 AND 899
当我处理这样的事情时,我会做这样的事情......
DECLARE @Autos Table (
ID varchar(100)
)
Insert into @Autos (ID) values ('R1')
Insert into @Autos (ID) values ('2')
Insert into @Autos (ID) values ('3')
Insert into @Autos (ID) values ('R4')
Insert into @Autos (ID) values ('5')
Insert into @Autos (ID) values ('R52')
Insert into @Autos (ID) values ('53')
Insert into @Autos (ID) values ('R8')
Select * from @Autos
Where cast(REPLACE(ID, 'R', '0') as integer) between 2 and 55
and ID not like 'R%'
输出是,
ID
---
2
3
5
53
--Kris
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.