在 Oracle DB 中有一个包含一些数据的表:
落后 | HNR | 街道 |
---|---|---|
00020 | 44 | 亚琛大街 |
00020 | 44/2 | 亚琛大街 |
00020 | 44/1 | 亚琛大街 |
00020 | 46 | 亚琛大街 |
00020 | 46/6 | 亚琛大街 |
00020 | 46/5 | 亚琛大街 |
00020 | 46/3 | 亚琛大街 |
00020 | 46/1 | 亚琛大街 |
00020 | 46/2 | 亚琛大街 |
00020 | 47 | 亚琛大街 |
00020 | 48 | 亚琛大街 |
00020 | 48/1 | 亚琛大街 |
00020 | 48/2 | 亚琛大街 |
00020 | 48A | 亚琛大街 |
请在此处找到一个最小的可重现示例:http ://www.sqlfiddle.com/#!4/19d625/1
现在我正在尝试通过"HNR"
按顺序对这些数据进行排序25 > 25A > 25B > 25/3
。因此,最高优先级有一个简单的数字,然后是带有字母的相同数字(也已排序),最后是带有子编号的相同数字/
(已排序)。
使用此代码
SELECT F.LAG,
F.HNR,
F.STREET
FROM DB.F F
ORDER BY F.LAG,
F.STREET,
TO_NUMBER(regexp_substr(F.HNR, '[[:digit:]]{1,4}')),
TO_CHAR(regexp_substr(F.HNR, '[[:alpha:]]{1}')),
TO_NUMBER(regexp_substr(F.HNR, '[^/]+', 1, 2));
我得到这个:
落后 | HNR | 街道 |
---|---|---|
00020 | 44/1 | 亚琛大街 |
00020 | 44/2 | 亚琛大街 |
00020 | 44 | 亚琛大街 |
00020 | 46/1 | 亚琛大街 |
00020 | 46/2 | 亚琛大街 |
00020 | 46/3 | 亚琛大街 |
00020 | 46/5 | 亚琛大街 |
00020 | 46/6 | 亚琛大街 |
00020 | 46 | 亚琛大街 |
00020 | 47 | 亚琛大街 |
00020 | 48/1 | 亚琛大街 |
00020 | 48/2 | 亚琛大街 |
00020 | 48A | 亚琛大街 |
00020 | 48 | 亚琛大街 |
而不是这个:
落后 | HNR | 街道 |
---|---|---|
00020 | 44 | 亚琛大街 |
00020 | 44/1 | 亚琛大街 |
00020 | 44/2 | 亚琛大街 |
00020 | 46 | 亚琛大街 |
00020 | 46/1 | 亚琛大街 |
00020 | 46/2 | 亚琛大街 |
00020 | 46/3 | 亚琛大街 |
00020 | 46/5 | 亚琛大街 |
00020 | 46/6 | 亚琛大街 |
00020 | 47 | 亚琛大街 |
00020 | 48 | 亚琛大街 |
00020 | 48A | 亚琛大街 |
00020 | 48/1 | 亚琛大街 |
00020 | 48/2 | 亚琛大街 |
我究竟做错了什么?
我见过SQL: ORDER BY 在特定列中使用子字符串……可能吗?并按字母排序,然后按数字排序,但我没有发现任何相关的东西。
除了对与您已经实现的那些字符相关的位进行排序之外,我还将根据中特殊字符的存在单独介绍排序。
HNR
您可以尝试使用
REGEXP_COUNT
它。您可以这样做:我在上面添加的两个附加排序标准将导致以下结果:
如您所见,按特定顺序使用它们将为 HNR 生成所需的排序顺序。
在 db<>fiddle的 SQL Fiddle上查看此解决方案的现场演示。
PostgreSQL
使用 PostgreSQL,您可以做到这一点,
这里的关键是
这将返回一个包含匹配项的 ARRAY,
我们只想订购
m[1]
{ 25, 25A, 25B }
。因此,将它们推到顶部,但是对于25/3
and25/4
order ASC(默认)这行吗?(我生成了自己的测试数据,以便更容易确认
'4'
之前的数据'44'
等。)这使:
这个想法是首先按前导数字排序,因此 4 在 5 之前,以此类推,然后按整个字符串,但将 any 更改
/
为上面的任意字符z
。