代码之家  ›  专栏  ›  技术社区  ›  Mike Wills

修复一个难看和混乱的SQL where语句

  •  3
  • Mike Wills  · 技术社区  · 14 年前

    我直接查询后端MS SQL Server以获取软件包。关键字段(车辆编号)定义为字母,尽管我们在字段中输入数值。只有一个例外,我们把一个“R”前的数字时,车辆正在退役(这意味着我们出售它或车辆报废)。假设用户做得对,我们就不会在使用这个方法时遇到问题(对与错不是这里的问题)

    快进到现在。我试图查询这些车辆编号(800-899)的一个子集,以便进行一些特殊处理。通过计算从'800'到'899'的范围,我们也可以得到80,81,等等。如果我将车辆编号转换为INT,我应该能够得到正确的范围。只是这些“R”车现在在踢我屁股。

    我试过了 where vehicleId not like 'R%' and cast(vehicleId as int) between 800 and 899

    工作是什么 where vehicleId not between '800' and '899' and cast(vehicleId as int) between 800 and 899' ,但我觉得必须有一个更好的方法,少让人困惑的方法。

    HAVING 以及一个子查询,所有子查询都产生一个转换错误。

    8 回复  |  直到 14 年前
        1
  •  6
  •   Falle1234    14 年前

    这应该可以做到,尽管它未经测试:

    where cast(replace(vehicleId,'R','') as int) between 800 and 899
    
        2
  •  5
  •   Dolph    14 年前

    使用 _ %

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

    您也可以这样组合它们:

    WHERE vehicleId LIKE '%8__'
    
        3
  •  1
  •   Cade Roux    14 年前

    无法保证优化器将以正确的顺序执行这些操作(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 
    
        4
  •  0
  •   Eric Petroelje    14 年前

    这个怎么样:

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

        5
  •  0
  •   coderguy123    14 年前
    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
  •   Snives    14 年前

    我不确定您是否希望包含“R%”记录,以及车辆ID的范围是否可变,但这可能会有所帮助。

    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
  •   KSimons    14 年前

    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
    

        8
  •  0
  •   HLGEM    14 年前

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

    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

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