我的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')))
答案 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