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

时间:2010-05-13 21:16:55

标签: sql sql-server

我直接在后端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的其他变体和一个子查询都会产生投射错误。

8 个答案:

答案 0 :(得分:6)

虽然未经测试,但这应该可以解决问题:

where cast(replace(vehicleId,'R','') as int) between 800 and 899

答案 1 :(得分:5)

使用_运算符代替%运算符:

WHERE vehicleId LIKE 'R8__' OR vehicleId LIKE '8__'

您也可以将它们组合起来:

WHERE vehicleId LIKE '%8__'

答案 2 :(得分:1)

无法保证优化器会以正确的顺序执行这些操作(目前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 

答案 3 :(得分:0)

这个怎么样:

WHERE vehicleId BETWEEN '800' and '899' AND LEN(vehicleId) = 3

不是很干净,但它会消除两个角色匹配。

答案 4 :(得分:0)

好的,你的问题是你正在尝试对字符串字段进行数学排序。

尝试使用派生表首先排除非数值,并将结果数据转换为int

select * from 
(select * from mytable where vehicleId not like 'R%')a
where cast(vehicleId as int) between 800 and 900

那不起作用,你可以试试     选择*来自     (从mytable中选择*,其中isnumeric(vehicleId)= 0)a     其中cast(vehicleId as int)介于800和900之间

isnumeric存在一些问题,但是如果它有效,你可以编写一个isint()函数并使用它。

答案 5 :(得分:0)

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
)

答案 6 :(得分:0)

我不确定您是否希望包含'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

答案 7 :(得分:0)

当我处理这样的事情时,我会这样做......

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

- 克里斯