Sql 在oracle 10g中,如何根据居住地址获得排序结果?

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有字符时,我不能认为它们是整数或数字,它们必须考虑为字

我想查询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有字符时,我不能认为它们是整数或数字,它们必须考虑为字符串。

< 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.