我正在使用不支持SQL RIGHT()函数的旧AS400,我需要根据数字的X最右字符选择行,该数字可能是7或8个字符长使用SQL。
如果我不能使用RIGHT,我怎么能得到我想要的,我不知道数字的确切长度?
这里是一些偶然有用的上下文:
这个数字是一个日期,但被存储为一个数字,所以第一个零被数据库删除,导致以零开头的日期,如01032016[读作01-03-2016]被修剪为1032016)。
数据库非常大,所以请求所有的行而不过滤这个字段会消耗相当多的资源和时间。
将数据库中的日期格式更改为更合理的格式会对我不维护的软件造成破坏性更改,这是至关重要的任务。
如果数据是作为数字存储的,那么DB不会去掉前导数字。无论你使用什么工具来查询数据,都可以做到这一点。
假设数据存储为打包或分区十进制,而不是整数(很可能),然后使用DIGITS()
将数字转换为固定字符,包括前导零,然后您可以使用SUBSTR()
SUBSTRING(mystr,character_length(mystr)-x+1,x)
或
SUBSTRING(mystr,character_length(mystr)-x+1)
是否支持模?
输入:1032016
// Outputs: 2016
YOURDATEASINT % 10000 AS Year
MOD(YOURDATEASINT, 10000) AS Year
// Outputs: 32016
YOURDATEASINT % 1000000 AS MonthYear
MOD(YOURDATEASINT, 1000000) AS MonthYear
// Outputs: 1032016
YOURDATEASINT % 100000000 AS DayMonthYear
MOD(YOURDATEASINT, 100000000) AS DayMonthYear
令我吃惊的是,作为数字存储的日期甚至不是YYYYMMDD形式。因此,对这些值的范围进行超过一年的过滤是特别烦人的。
如果你有创建表和索引的权限,你可以做的一件事就是创建一个日期表,它简单地列出一个非常大的范围内所有可能的日期。(15万张记录涵盖了400多年,按照今天的标准,这只是一张小桌子。)这个表将包括几种格式,其中至少有一种是真正的date类型列,另一种是您要处理的格式(在本例中,是表示MMDDYYYY或DDMMYYYY的8位数字)。然后,您可以使用连接来利用SQL查询引擎的强度,而不必对每一行数据执行函数计算(如果使用内联SQL转换数据,则必须执行函数计算)。虽然substring(digits(date_column),x,y)是一个选项,但另一个选项是MOD函数和除法的组合。例如,要获取年份,使用this: SELECT MOD(date_column,10000)
,要获取日期,使用this: CAST(MOD(date_column,1000000)/10000 AS INT)
,要获取月份,使用this: CAST(date_column/1000000 AS INT)
。