我有一个PostgreSQL表,并希望按案例分层排序。下面是一个示例:
> Name | Port
> ----------------------------
> Switch1 | GigabitEthernet2/2
> Switch1 | GigabitEthernet1/2
> Switch2 | 1.23
> Switch2 | 1.21
> Switch1 | GigabitEthernet2/1
> Switch1 | GigabitEthernet1/1/3
> Switch1 | FastEthernet1/1/14
> Switch1 | FastEthernet3/0/19
> Switch1 | FastEthernet3/0/20
> Switch2 | Port-Channel3
> Switch1 | GigabitEthernet3/0/4
> Switch1 | GigabitEthernet3/1/3
> Switch1 | FastEthernet3/0/2
> Switch2 | 1.14
> Switch2 | Port-Channel6
排序/排序后,它应该是这样的:
> Name | Port
> ----------------------------
> Switch1 | FastEthernet1/1/14
> Switch1 | FastEthernet3/0/2
> Switch1 | FastEthernet3/0/19
> Switch1 | FastEthernet3/0/20
> Switch1 | GigabitEthernet1/2
> Switch1 | GigabitEthernet2/1
> Switch1 | GigabitEthernet2/2
> Switch1 | GigabitEthernet1/1/3
> Switch1 | GigabitEthernet3/0/4
> Switch1 | GigabitEthernet3/1/3
> Switch2 | 1.14
> Switch2 | 1.21
> Switch2 | 1.23
> Switch2 | Port-Channel3
> Switch2 | Port-Channel6
我试图用逐案订购做一些事情。下面是一个示例:
SELECT device.name, device_port.port
FROM device
JOIN device_port ON device.ip = device_port.ip
ORDER BY CASE WHEN device_port.port like 'Fast%' THEN string_to_array(substr(device_port.port, position('/' in device_port.port)-1 ),'/')::float[]
WHEN device_port.port like 'Gigabit%' THEN string_to_array(substr(device_port.port,16),'/')::float[]
WHEN device_port.port like 'Port-channel%' THEN string_to_array(substr(device_port.port,13),'/')::float[] END;
但是这样就不可能首先按 device.name 和端口名称对其进行排序。例如,结果将是:
> Name | Port
> ----------------------------
> Switch1 | FastEthernet1/1/14
> Switch1 | GigabitEthernet1/2
> Switch1 | FastEthernet3/0/2
> Switch1 | GigabitEthernet3/0/4
等等...
使用 regexp_replace()
.
在示例中,为简单起见,我使用了一个表,并选择port_name
和port_number
以便更好地理解。
select
*,
regexp_replace(port, '[0-9/.]', '', 'g') port_name,
string_to_array(regexp_replace(port, '[A-Za-z-]', '', 'g'), '/')::float[] port_number
from
device
order by
name,
regexp_replace(port, '[0-9/.]', '', 'g'),
string_to_array(regexp_replace(port, '[A-Za-z-]', '', 'g'), '/')::float[];
name | port | port_name | port_number
---------+----------------------+-----------------+-------------
Switch1 | FastEthernet1/1/14 | FastEthernet | {1,1,14}
Switch1 | FastEthernet3/0/2 | FastEthernet | {3,0,2}
Switch1 | FastEthernet3/0/19 | FastEthernet | {3,0,19}
Switch1 | FastEthernet3/0/20 | FastEthernet | {3,0,20}
Switch1 | GigabitEthernet1/1/3 | GigabitEthernet | {1,1,3}
Switch1 | GigabitEthernet1/2 | GigabitEthernet | {1,2}
Switch1 | GigabitEthernet2/1 | GigabitEthernet | {2,1}
Switch1 | GigabitEthernet2/2 | GigabitEthernet | {2,2}
Switch1 | GigabitEthernet3/0/4 | GigabitEthernet | {3,0,4}
Switch1 | GigabitEthernet3/1/3 | GigabitEthernet | {3,1,3}
Switch2 | 1.14 | | {1.14}
Switch2 | 1.21 | | {1.21}
Switch2 | 1.23 | | {1.23}
Switch2 | Port-Channel3 | Port-Channel | {3}
Switch2 | Port-Channel6 | Port-Channel | {6}
(15 rows)
带int[]
的选项。
我以为你故意使用了float[]
类型。如果要比较int[]
值(并将浮点数转换为 int 数组),则可以即时使用translate()
:
select
*,
regexp_replace(port, '[0-9/.]', '', 'g') port_name,
string_to_array(
regexp_replace(
translate(port, '.', '/'),
'[A-Za-z-]', '', 'g'),
'/')::int[] port_number
from
device
order by
name,
regexp_replace(port, '[0-9/.]', '', 'g'),
string_to_array(
regexp_replace(
translate(port, '.', '/'),
'[A-Za-z-]', '', 'g'),
'/')::int[];
name | port | port_name | port_number
---------+------+-----------+-------------
Switch2 | 1.1 | | {1,1}
Switch2 | 1.2 | | {1,2}
Switch2 | 1.14 | | {1,14}
Switch2 | 1.21 | | {1,21}
Switch2 | 1.23 | | {1,23}
(5 rows)
@klin:哇,这么简单的代码,几乎按预期工作!非常感谢!不知道这样的正则表达式函数是存在的。
唯一缺少的是将 {1.14} 分离成类似 {1,14} 的数组。
例如,在这种情况下,当前排序失败:
> Name | Port
> ------------------
> Switch2 | 1.1
> Switch2 | 1.18
> Switch2 | 1.19
> Switch2 | 1.2
> Switch2 | 1.20
> Switch2 | 1.21
但应该像
> Name | Port
> ------------------
> Switch2 | 1.1
> Switch2 | 1.2
> Switch2 | 1.18
> Switch2 | 1.19
> Switch2 | 1.20
> Switch2 | 1.21
我认为解决方案应该是这样的:
order by
name,
regexp_replace(port, '[0-9/.]', '', 'g'),
string_to_array(regexp_replace(port, '[A-Za-z-]', '', 'g'), '/')::float[],
string_to_array(regexp_matches(port, '**finding a . in the string**', **give back full string matching pattern** , 'g'), '.')::float[];
问题:
1)你能帮我构建这个regexp_matches函数,以便它在找到点时总是返回完整的字符串吗?
2) 正则表达式替换表达式中的"是什么意思?它通常应该给出替换模式。
再次感谢您的帮助!