字母数字值之间的SQL

时间:2015-12-02 19:06:36

标签: db2

我的DB2表中有一个字母数字列。我正在搜索两个用户输入值之间的结果。

示例数据

ABC300
ABC2002
CDEF200
ABC429
UOH250

示例SQL查询

SELECT VALUE
FROM TABLE
WHERE VALUE BETWEEN 'ABC200' AND 'ABC700'

返回值

ABC300
ABC2002
ABC429

ABC2002是一个不受欢迎的结果。我理解为什么查询返回此结果。它正在进行字符串比较,发现“ABC2”介于“ABC200”和“ABC700”之间,并停止比较。

我知道PATINDEX,但我使用的是DB2,没有相应的东西。

我尝试过像这样使用TRANSLATE:

WHERE TRANSLATE(LOWER(VALUE), '', 'abcdefghijklmnopqrstuvwxyz') 
    BETWEEN TRANSLATE(LOWER('ABC200'), '', 'abcdefghijklmnopqrstuvwxyz')
    AND TRANSLATE(LOWER('ABC700'), '', 'abcdefghijklmnopqrstuvwxyz')

就像这样:

WHERE TRANSLATE(LOWER(VALUE), '', 'abcdefghijklmnopqrstuvwxyz') 
    BETWEEN 200 AND 700

并且都没有给出理想的结果。

字母前缀不是固定值或固定长度。

有什么想法吗?谢谢。

修改

在解释了这里的问题之后我就能解决它(参见:Rubber Duck Debugging)。以下是我为解决问题所做的工作:

SELECT VALUE
FROM TABLE
WHERE TRIM(TRANSLATE(VALUE, '', ' 0123456789')) 
    BETWEEN TRIM(TRANSLATE(UPPER(@VALUE_HI), '', ' 0123456789')) 
    AND TRIM(TRANSLATE(UPPER(@VALUE_LO), '', ' 0123456789')) 
AND TRIM(TRANSLATE(VALUE, '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')) 
    BETWEEN INT(TRIM(TRANSLATE(UPPER(@VALUE_LO), '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))) 
    AND INT(TRIM(TRANSLATE(UPPER(@VALUE_HI), '', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'))) 

1 个答案:

答案 0 :(得分:1)

如果您需要此功能,则应将此列拆分为两个单独的列。字符列应存储前缀,数字列应存储该数字。

这里的问题是您需要执行两种不同的比较操作:

  • 前缀的字符串比较。
  • 数字部分的数字比较。

你不能通过一次比较来挤压这两件事。

如果可能,您应该永久更改基础数据。之所以出现这个问题,是因为您在一个字段中存储了两条信息(一个类别和一个等级),这违背了良好的数据库设计。

但即使你不能,这仍然是正确的方法:使用子查询生成两个字段。

with col_split as (
    select
          translate(value, '', '1234567890') prefix,
          cast(translate(lower(value), '', 'abcdefghijklmnopqrstuvwxyz') as int) number
       from table
)
select * 
   from col_split
   where 
      prefix = 'ABC' and
      number between 200 and 700