2016-06-01 9 views
3

私はPostgreSQLのテーブルを持っており、ケースを階層的にそれを注文したいを考えながら。次に例を示します。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 

私はCASE BY ORDERで何かをしようとしています。ここに例があります:

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 

などなど:結果は次のように例えばでしょうか?結果なしで何時間も試しました。

ありがとうございます!

答えて

2

使用regexp_replace()

例では、わかりやすくするために1つの表を使用し、port_nameport_numberを選択します。 int[]

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) 

オプション。

私はあなたが意図的にタイプ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) 
0

@klinを:うわー、このような簡単なコードとほぼ期待通りに動作します!どうもありがとう!そのような正規表現関数が存在することを知らなかった。

欠く唯一のものは、{1,14}のような配列に{1.14}の分離です。

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[]; 

:私は解決策は、そのようなものであるべきだと思う

> 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 

のようにする必要があります:

現在のソートは、このような状況で、たとえば失敗します質問:

1)このregexp_matches関数をビルドして、ドットが見つかると常にフルストリングを返すように助けてくれますか?

2)「」あなたの正規表現では表現が何を意味するかを交換するのですか?それは通常、置換パターンを与えるべきです。あなたの助けのための

もう一度感謝!

+1

編集された答えをご覧ください。 'regexp_replace(port、 '[0-9/\。]'、 ''、 'g')の空文字列は、' '[0-9/\。]' 'にマッチするすべてのトークンが ' 「ポート」。 – klin

+0

これは簡単な解決策のようです。今はすべてが期待通りに機能します。私はあなたの支援に感謝します! – Grunner

関連する問題