Sql 在oracle 10g中,如何根据居住地址获得排序结果?
我想查询Oracle 10g数据库,并根据住宅地址按升序或降序得到结果。所以问题是建筑地址在时间上是110C或200D的形式,所以根据sql“order by”asc或desc,我得到的结果是20之前的200D。 例如,如果地址为10 110 112 200D 232 95 20 100A 1050 944 按升序,它将导致:-Sql 在oracle 10g中,如何根据居住地址获得排序结果?,sql,regex,oracle,oracle10g,Sql,Regex,Oracle,Oracle10g,我想查询Oracle 10g数据库,并根据住宅地址按升序或降序得到结果。所以问题是建筑地址在时间上是110C或200D的形式,所以根据sql“order by”asc或desc,我得到的结果是20之前的200D。 例如,如果地址为10 110 112 200D 232 95 20 100A 1050 944 按升序,它将导致:- 10 100 100A 1050 110 112 20 200D 232 944 95 问题是,当Adress有字符时,我不能认为它们是整数或数字,它们必须考虑为字
10 100 100A 1050 110 112 20 200D 232 944 95
问题是,当Adress有字符时,我不能认为它们是整数或数字,它们必须考虑为字符串。 < P>唯一的方法是将街道号码解析成数字和非数字部分,并将它们存储在单独的列中,这样就可以先在数字部分上索引(或按顺序排序)。(作为一个数字)然后是非数字部分。可能会编写一个表达式来实现这一点,但随后会丢失任何索引(如果这很重要的话)
在Oracle 11中,有一个REGEXP_SUBSTR函数可以用来实现这一点,但我不确定它是否存在于Oracle 10g中。使用正则表达式: 警告!前面可能有不工作的代码。我目前没有Oracle实例来测试它
REGEXP\u SUBSTR
将找到数字的子字符串,该子字符串应该开始地址,将其转换为实数并按其排序
警告:您必须改进查询以处理数字不存在的情况。但是,这个答案可以让您很好地开始
当需要微调查询时,以下是您应该使用的资源:
是的,
REGEXP\u SUBSTR
在Oracle 10g中可用。我没有使用Oracle的经验,但通常使用SQL之类的工具会有所帮助:
ORDER BY CAST(house AS integer), house
因此,基本上您首先按字段的整数部分排序(CAST应忽略所有尾随的非数字字符),如果它们相同,则应将它们作为字符串进行比较,以便100A在100b之前
显然,这在Oracle中不起作用。请参阅注释我知道您有两个基本选项:
1.强制将字段设置为一致的格式
2.将数字部分和非数字部分分开 对于选项一,您可以将
'10'
更改为'00010-'
,将'100A'
更改为'00100A'
,等等。然后他们会自然地进行排序
对于选项二,您可以将'10'
更改为(10',)
,将'100A'
更改为(100,'A')
,等等。然后分别按两部分(数字和非数字)排序
无论哪种方式,您都需要更多地了解(或告诉我们)数据的最终特征。(模式是否总是[numeric][alpha],[alpha]部分是否总是1个字符长,您是否有过建筑名称等?)基于正则表达式的解决方案更加优雅。但是,如果您想先使用数字排序对数字组件进行排序,然后使用字符排序对字符组件进行排序,那么您也可以使用
TRANSLATE
函数
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select '10' addr from dual union all
3 select '100' from dual union all
4 select '100A' from dual union all
5 select '1050' from dual union all
6 select '110' from dual union all
7 select '200D' from dual union all
8 select '20' from dual
9 )
10 select addr,
11 to_number( translate( addr,
12 '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ',
13 '1234567890' ) ) addr_num,
14 translate( addr,
15 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
16 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') addr_str
17 from x
18 order by to_number( translate( addr,
19 '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ',
20 '1234567890' ) ),
21 translate( addr,
22 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
23* 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
SQL> /
ADDR ADDR_NUM ADDR_STR
---- ---------- ----------------
10 10
20 20
100A 100 A
100 100
110 110
200D 200 D
1050 1050
7 rows selected.
为什么20会在112和232之间?20不应该在10和100之间排序吗?这不是一个sql语言解决方案,但可能会给你一些想法…这可能是一个打字错误,因为OP很好地描述了这个问题…@Justin Cave:显示的数据列表(
112,20200d
)是OP从字母数字排序中得到的。OP想要的是你所描述的(201112200d
)有趣的是,提到REGEXP\u SUBSTR
会得到投票,但使用REGEXP\u SUBSTR
发布实际答案不会…对“7个小矮人”来说有点不可靠但是在没有明确字符串特征的操作的情况下,这肯定是有效的:)出于兴趣,如果在Oracle中为CAST指定“A1”、“1B2”或“A1B2”,会发生什么情况?这不起作用:将包含非数字字符的字段强制转换为整数将导致Oracle中出现“无效数字”错误。任何在转换过程中丢弃非数字尾随字符的DB都不符合SQL-92标准(其中引入了cast
)@Allan感谢您的澄清。使用“7个小矮人”作为名称有点不可靠。但在没有明确说明字符串的确切特征的情况下,这肯定是可行的:)@Dems同意。此外,OP必须根据数据进行调整。但对于必须以数字开头的地址,这就行了。@Adrian-谢谢Adrian,您的查询字符串可以满足我的需要:)
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select '10' addr from dual union all
3 select '100' from dual union all
4 select '100A' from dual union all
5 select '1050' from dual union all
6 select '110' from dual union all
7 select '200D' from dual union all
8 select '20' from dual
9 )
10 select addr,
11 to_number( translate( addr,
12 '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ',
13 '1234567890' ) ) addr_num,
14 translate( addr,
15 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
16 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') addr_str
17 from x
18 order by to_number( translate( addr,
19 '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ',
20 '1234567890' ) ),
21 translate( addr,
22 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
23* 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
SQL> /
ADDR ADDR_NUM ADDR_STR
---- ---------- ----------------
10 10
20 20
100A 100 A
100 100
110 110
200D 200 D
1050 1050
7 rows selected.