繁体   English   中英

修复SQL where丑陋且令人困惑的语句

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM