Присоединяйтесь к inet [] к inet - PullRequest
1 голос
/ 29 апреля 2019

Я пытаюсь объединить две таблицы:

peering_autonomoussystem.potential_internet_exchange_peering_sessions (которая содержит массив адресов ipv4 или ipv6)

и

peeringdb_networkixlan.ipaddr4 (которыесодержит простой адрес ipv4)

и

peeringdb_networkixlan.ipaddr6 (который содержит простой адрес ipv6)

У меня возникают проблемы с выяснением, как связать inetзначение со значениями из необъявленного массива inet[], чтобы завершить объединение.

Я экспериментировал с различными вариантами, чтобы попытаться заставить что-то работать, но я не добиваюсь больших успехов.Я задаюсь вопросом, может ли кто-нибудь быть в состоянии бросить несколько указателей в моем направлении?

select
 peering_autonomoussystem.asn,
 peering_autonomoussystem.name,
 unnest(peering_autonomoussystem.potential_internet_exchange_peering_sessions),
 peeringdb_networkixlan.ipaddr4,
 peeringdb_networkixlan.ipaddr6,
 peeringdb_networkixlan.name
from
 (
 select unnest(peering_autonomoussystem.potential_internet_exchange_peering_sessions)
     from peering_autonomoussystem
 ) as inet(ip)
join
 peeringdb_networkixlan
on
 peeringdb_networkixlan.ipaddr4 = inet.ip

ERROR:  missing FROM-clause entry for table "peering_autonomoussystem"
LINE 2:  peering_autonomoussystem.asn,
         ^
SQL state: 42P01
Character: 9
peering_manager=# select
peering_manager-#  peering_autonomoussystem.asn,
peering_manager-#  peering_autonomoussystem.name,
peering_manager-#  unnest(peering_autonomoussystem.potential_internet_exchange_peering_sessions),
peering_manager-#  peeringdb_networkixlan.ipaddr4,
peering_manager-#  peeringdb_networkixlan.ipaddr6,
peering_manager-#  peeringdb_networkixlan.name
peering_manager-# from
peering_manager-#  peering_autonomoussystem
peering_manager-# join
peering_manager-#  peeringdb_networkixlan
peering_manager-# on
peering_manager-#  peeringdb_networkixlan.ipaddr4 @> peering_autonomoussystem.potential_internet_exchange_peering_sessions
peering_manager-#
peering_manager-# ;
ERROR:  operator does not exist: inet @> inet[]
LINE 13:  peeringdb_networkixlan.ipaddr4 @> peering_autonomoussystem....
                                         ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
peering_manager=#

Вот наборы данных из двух таблиц, с которыми я работаю:

peering_manager=# \d peering_autonomoussystem
                                                        Table "public.peering_autonomoussystem"
                    Column                    |           Type           | Collation | Nullable |                       Default
----------------------------------------------+--------------------------+-----------+----------+------------------------------------------------------
 id                                           | integer                  |           | not null | nextval('peering_autonomoussystem_id_seq'::regclass)
 asn                                          | bigint                   |           | not null |
 name                                         | character varying(128)   |           | not null |
 comment                                      | text                     |           | not null |
 ipv6_max_prefixes                            | integer                  |           | not null |
 ipv4_max_prefixes                            | integer                  |           | not null |
 updated                                      | timestamp with time zone |           |          |
 irr_as_set                                   | character varying(255)   |           |          |
 ipv4_max_prefixes_peeringdb_sync             | boolean                  |           | not null |
 ipv6_max_prefixes_peeringdb_sync             | boolean                  |           | not null |
 irr_as_set_peeringdb_sync                    | boolean                  |           | not null |
 created                                      | timestamp with time zone |           |          |
 potential_internet_exchange_peering_sessions | inet[]                   |           | not null |
 contact_email                                | character varying(254)   |           | not null |
 contact_name                                 | character varying(50)    |           | not null |
 contact_phone                                | character varying(20)    |           | not null |
Indexes:
    "peering_autonomoussystem_pkey" PRIMARY KEY, btree (id)
    "peering_autonomoussystem_asn_ec0373c4_uniq" UNIQUE CONSTRAINT, btree (asn)
Check constraints:
    "peering_autonomoussystem_ipv4_max_prefixes_check" CHECK (ipv4_max_prefixes >= 0)
    "peering_autonomoussystem_ipv6_max_prefixes_check" CHECK (ipv6_max_prefixes >= 0)
Referenced by:
    TABLE "peering_directpeeringsession" CONSTRAINT "peering_directpeerin_autonomous_system_id_691dbc97_fk_peering_a" FOREIGN KEY (autonomous_system_id) REFERENCES peering_autonomoussystem(id) DEFERRABLE INITIALLY DEFERRED
    TABLE "peering_internetexchangepeeringsession" CONSTRAINT "peering_peeringsessi_autonomous_system_id_9ffc404f_fk_peering_a" FOREIGN KEY (autonomous_system_id) REFERENCES peering_autonomoussystem(id) DEFERRABLE INITIALLY DEFERRED

peering_manager=# select
 peering_autonomoussystem.asn,
 peering_autonomoussystem.name,
 unnest(peering_autonomoussystem.potential_internet_exchange_peering_sessions)
from
 peering_autonomoussystem limit 10;
  asn  |              name              |         unnest
-------+--------------------------------+-------------------------
  5400 | BT                             | 2001:504:1::a500:5400:1
  5400 | BT                             | 198.32.160.80
 21724 | Radiant Communications Toronto | 2001:504:1a::34:102
  8002 | Stealth Communications         | 2001:504:1::a500:8002:1
  8002 | Stealth Communications         | 2001:504:36::1f42:0:1
  8002 | Stealth Communications         | 206.82.104.194
 10835 | Visionary Communications, Inc. | 2001:504:16::2a53
 10835 | Visionary Communications, Inc. | 206.81.80.57
 23473 | Pavlov Media INC.              | 2001:504:17:115::224
 23473 | Pavlov Media INC.              | 206.126.115.224
(10 rows)

peering_manager=#
peering_manager=# \d peeringdb_networkixlan;
                                      Table "public.peeringdb_networkixlan"
   Column   |          Type          | Collation | Nullable |                      Default
------------+------------------------+-----------+----------+----------------------------------------------------
 id         | integer                |           | not null | nextval('peeringdb_networkixlan_id_seq'::regclass)
 asn        | bigint                 |           | not null |
 ipaddr6    | inet                   |           |          |
 ipaddr4    | inet                   |           |          |
 is_rs_peer | boolean                |           | not null |
 ix_id      | integer                |           | not null |
 name       | character varying(255) |           | not null |
 ixlan_id   | integer                |           | not null |
Indexes:
    "peeringdb_networkixlan_pkey" PRIMARY KEY, btree (id)
Check constraints:
    "peeringdb_networkixlan_ix_id_check" CHECK (ix_id >= 0)
    "peeringdb_networkixlan_ixlan_id_check" CHECK (ixlan_id >= 0)
Referenced by:
    TABLE "peeringdb_peerrecord" CONSTRAINT "peeringdb_peerrecord_network_ixlan_id_97d3feaa_fk_peeringdb" FOREIGN KEY (network_ixlan_id) REFERENCES peeringdb_networkixlan(id) DEFERRABLE INITIALLY DEFERRED

peering_manager=# select
peering_manager-#  peeringdb_networkixlan.ipaddr4,
peering_manager-#  peeringdb_networkixlan.ipaddr6,
peering_manager-#  name
peering_manager-# from
peering_manager-#  peeringdb_networkixlan
peering_manager-# where
peering_manager-#  ipaddr6 = '2001:504:1::a500:5400:1'
peering_manager-# or
peering_manager-#  ipaddr4 = '198.32.160.80'
peering_manager-# or
peering_manager-#  ipaddr6 = '2001:504:1a::34:102'
peering_manager-# or
peering_manager-#  ipaddr6 = '2001:504:1::a500:8002:1'
peering_manager-# or
peering_manager-#  ipaddr4 = '206.82.104.194'
peering_manager-# or
peering_manager-#  ipaddr6 = '2001:504:16::2a53'
peering_manager-# or
peering_manager-#  ipaddr4 = '206.81.80.57'
peering_manager-# or
peering_manager-#  ipaddr6 = '2001:504:17:115::224'
peering_manager-# or
peering_manager-#  ipaddr4 = '206.126.115.224';
     ipaddr4     |         ipaddr6         |                     name
-----------------+-------------------------+----------------------------------------------
 206.108.34.102  | 2001:504:1a::34:102     | TorIX
 206.126.115.224 | 2001:504:17:115::224    | Digital Realty New York
 198.32.160.80   | 2001:504:1::a500:5400:1 | NYIIX
 198.32.160.33   | 2001:504:1::a500:8002:1 | NYIIX
 206.81.80.57    | 2001:504:16::2a53       | SIX Seattle: MTU 1500
 206.82.104.194  | 2001:504:36::1f42:0:1   | DE-CIX New York: DE-CIX New York Peering LAN
(6 rows)

peering_manager=#

ОБНОВЛЕНИЯ:

После предложений @Laurenz Albe я уточнил запрос, чтобы использовать ANY, который дал положительные результаты, хотя запрос должен быть уточнен.Используя pas.asn = 812 в качестве примера:

select
 pas.asn asnumber,
 pas.name asname,
 pas.potential_internet_exchange_peering_sessions potential,
 pdbnil.ipaddr4 ipv4,
 pdbnil.ipaddr6 ipv6,
 pdbnil.name ixname
from
 peering_autonomoussystem pas
join
 peeringdb_networkixlan pdbnil
on
 pdbnil.ipaddr4 = any(pas.potential_internet_exchange_peering_sessions)
or
 pdbnil.ipaddr6 = any(pas.potential_internet_exchange_peering_sessions)
where pas.asn = 812;
 asnumber |    asname    |                            potential                             |     ipv4      |        ipv6        |     ixname
----------+--------------+------------------------------------------------------------------+---------------+--------------------+-----------------
      812 | Rogers Cable | {2001:504:12::14,198.32.134.32,2001:504:1a::34:29,206.108.34.29} | 198.32.134.32 | 2001:504:12::14    | Equinix Seattle
      812 | Rogers Cable | {2001:504:12::14,198.32.134.32,2001:504:1a::34:29,206.108.34.29} | 206.108.34.29 | 2001:504:1a::34:29 | TorIX
(2 rows)

Мой желаемый результат для вышеупомянутого будет видеть 4 строки, по одной для каждого из значений в массиве potential.Я верил, что OR в соединении достигнет этого хотя бы частично, но, похоже, нет.

1 Ответ

0 голосов
/ 29 апреля 2019

Есть два варианта условия соединения:

  1. Оператор с ANY:

    peeringdb_networkixlan.ipaddr4
    = ANY (peering_autonomoussystem.potential_internet_exchange_peering_session)
    

    Эта версия может использовать индекс b-дерева для peeringdb_networkixlan(ipaddr4).

  2. Массив & ldquo; сдерживание & rdquo; Оператор:

    ARRAY[peeringdb_networkixlan.ipaddr4]
    <@ peering_autonomoussystem.potential_internet_exchange_peering_session
    

    Эта версия может использовать индекс GIN для peering_autonomoussystem(potential_internet_exchange_peering_session).

Вы можете попробовать оба варианта и посмотреть, какой из них лучше для вашего случая.

В общем, было бы лучше , а не использовать массив, если вы хотите объединить отдельные элементы массива. Обычно в этом случае лучше нормализовать данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...