powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос по КЛАДР
10 сообщений из 10, страница 1 из 1
Вопрос по КЛАДР
    #39680301
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я не придумал, где нужно опубликовать этот вопрос, поэтому решил тут, поскольку БД Oracle.

Есть информационная система, в которую интегрирован КЛАДР таким образом:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CREATE TABLE BM_ADDRESS_OBJECT
(
  ADDRESS_OBJECT_ID       NUMBER                NOT NULL,
  ADDRESS_OBJECT_TYPE_ID  NUMBER,
  PARENT_OBJECT_ID        NUMBER,
  NAME                    VARCHAR2(255 BYTE),
  KLADR_CODE              VARCHAR2(255 BYTE),
  PARENT_KLADR_CODE       VARCHAR2(255 BYTE)
);
CREATE TABLE BM_ADDRESS_OBJECT_TYPE
(
  ADDRESS_OBJECT_TYPE_ID  NUMBER                NOT NULL,
  SHORT_NAME              VARCHAR2(255 BYTE)    NOT NULL,
  NAME                    VARCHAR2(255 BYTE)    NOT NULL,
  KLADR_CODE              NUMBER                NOT NULL,
  PARENT_KLADR_CODE       NUMBER,
  ADDRESS_LEVEL           NUMBER
);


Есть EAV-таблица атрибутов клиентов и один из атрибутов address_id ссылается как раз на BM_ADDRESS_OBJECT.ADDRESS_OBJECT_ID.

Структуру адреса я достаю таким образом:
Код: plsql
1.
2.
3.
4.
5.
select *
from BM_ADDRESS_OBJECT AO
join BM_ADDRESS_OBJECT_TYPE AT on (AT.ADDRESS_OBJECT_TYPE_ID = AO.ADDRESS_OBJECT_TYPE_ID)
connect by AO.ADDRESS_OBJECT_ID = prior AO.PARENT_OBJECT_ID
start with AO.ADDRESS_OBJECT_ID = <address_id>


Визуально результат вполне понятный:
ADDRESS_OBJECT_IDADDRESS_OBJECT_TYPE_IDPARENT_OBJECT_IDNAMEKLADR_CODEPARENT_KLADR_CODEADDRESS_OBJECT_TYPE_ID_1SHORT_NAMENAME_1KLADR_CODE_1PARENT_KLADR_CODE_1ADDRESS_LEVEL108432191613121019451кв.Квартира-173121019593265935123xx00000100000yy0004xx00000100000yy593ДОМДом601626593518310070Первомайскаяxx00000100000yyxx000001000183улУлица52951007042010068Первомайскxx000001000xx000000000420гГород301310068409Субъектxx000000000409Суб.Субъект1061

Мне нужно из этого адреса извлечь населенный пункт (город), улицу и номер дома.
Но я с КЛАДР особо не работал и не знаю, как в нем структурирована информация.
Могу ли я ориентироваться на ADDRESS_LEVEL?
Или уровень вложенности адреса не является фиксированным и нужно ориентироваться на наименования типа объектов?

И второй вопрос — не поможете составить запрос, чтобы сразу извлечь нужные значения адресных фрагментов (город, улица, дом), не строя полную иерархию и извлекая из нее фрагменты?
Или без вложенного запроса с полной иерархией не обойтись?
В идеале я бы хотел использовать запрос примерно так:
Код: plsql
1.
2.
3.
select client.client_id, adr.city, adr.street, adr.building
from client
join <запрос из КЛАДР> adr on (adr.address_id = client.address_id)
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680389
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КЛАДР - классификатор.
Вы могли бы с ним уверенно работать вообще без "деревяшек", на одних лайках, если освоите маску "_" (любой символ).
И (когда я много-много лет назад это делал) это реально упрощает все дело.
К огромному сожалению, КЛАДР - ВСЁ. с 1 января этого года больше не поддерживается.
Теперь только ФИАС.
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680398
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В EAV хранится не идентификатор КЛАДР, а идентификатор на справочник адресов, который создается из КЛАДР, но без позиционной символьной привязке. Поэтому like тут не применим, необходим именно рекурсивный запрос.
Вопрос в том, фиксированы ли в КЛАДР уровни адресных объектов. То есть всегда ли 5 это улица или в некоторых случаях у улиц могут быть другие уровни?
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680403
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никак не соображу, как задать правильный запрос.

Вот запрос, который отбирает список нужных клиентов и для каждого из них получает ссылку на адрес в КЛАДР:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select S.SERVICE_ID, C.CUSTOMER_ID, CC.VALUE as CLIENT, to_number(CA.VALUE) as ADDRESS_ID
from SERVICES S
join CUSTOMERS C on (C.CUSTOMER_ID = S.CUSTOMER_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 90)
where S.TYPE_ID = 204
and S.STATUS != -20
and months_between(trunc(sysdate), S.RECKONING_DATE) < 10



Вот рекурсивный запрос, который возвращает цепочку адресных фрагментов из КЛАДР для одного конкретного клиента:
Код: plsql
1.
2.
3.
4.
5.
select *
from BM_ADDRESS_OBJECT AO
join BM_ADDRESS_OBJECT_TYPE AT on (AT.ADDRESS_OBJECT_TYPE_ID = AO.ADDRESS_OBJECT_TYPE_ID)
connect by AO.ADDRESS_OBJECT_ID = prior AO.PARENT_OBJECT_ID
start with AO.ADDRESS_OBJECT_ID = 1084321916



Я хочу получить цепочки адресных фрагментов не для одного клиента, а для всех клиентов из первой выборки.
Но не пойму, как это сделать.

Такой запрос возвращает список нужных клиентов и нижний уровень КЛАДР (квартиры или дома).
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select S.SERVICE_ID, C.CUSTOMER_ID, to_number(CA.VALUE) as ADDRESS_ID
, AO.*, AT.*
from SERVICES S
join CUSTOMERS C on (C.CUSTOMER_ID = S.CUSTOMER_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 90)
join BM_ADDRESS_OBJECT AO on (AO.ADDRESS_OBJECT_ID = to_number(CA.VALUE))
join BM_ADDRESS_OBJECT_TYPE AT on (AT.ADDRESS_OBJECT_TYPE_ID = AO.ADDRESS_OBJECT_TYPE_ID)
where S.TYPE_ID = 204
and S.STATUS != -20
and months_between(trunc(sysdate), S.RECKONING_DATE) < 10



Как мне из него построить цепочку адресных фрагментов?
Такой запрос неверен:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select S.SERVICE_ID, C.CUSTOMER_ID, to_number(CA.VALUE) as ADDRESS_ID
, AO.*, AT.*
from SERVICES S
join CUSTOMERS C on (C.CUSTOMER_ID = S.CUSTOMER_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 90)
join BM_ADDRESS_OBJECT AO on (AO.ADDRESS_OBJECT_ID = to_number(CA.VALUE))
join BM_ADDRESS_OBJECT_TYPE AT on (AT.ADDRESS_OBJECT_TYPE_ID = AO.ADDRESS_OBJECT_TYPE_ID)
where S.TYPE_ID = 204
and S.STATUS != -20
and months_between(trunc(sysdate), S.RECKONING_DATE) < 10
connect by AO.ADDRESS_OBJECT_ID = prior AO.PARENT_OBJECT_ID
start with AO.ADDRESS_OBJECT_ID = to_number(CA.VALUE)


А такой возможно и верен, но его завершения я не дождался:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
select *
from BM_ADDRESS_OBJECT AO
join BM_ADDRESS_OBJECT_TYPE AT on (AT.ADDRESS_OBJECT_TYPE_ID = AO.ADDRESS_OBJECT_TYPE_ID)
connect by AO.ADDRESS_OBJECT_ID = prior AO.PARENT_OBJECT_ID
start with AO.ADDRESS_OBJECT_ID in
(
select to_number(CA.VALUE) as ADDRESS_ID
from SERVICES S
join CUSTOMERS C on (C.CUSTOMER_ID = S.CUSTOMER_ID)
join BM_CUSTOMER_CONTACT CC on (CC.CUSTOMER_ID = C.CUSTOMER_ID and CC.CONTACT_DICT_ID = 100)
join BM_CUSTOMER_CONTACT CA on (CA.CUSTOMER_ID = C.CUSTOMER_ID and CA.CONTACT_DICT_ID = 90)
where S.TYPE_ID = 204
and S.STATUS != -20
and months_between(trunc(sysdate), S.RECKONING_DATE) < 10
)



В принципе в выборке будет не очень много строк (сотни, может быть тысячи), поэтому наверное возможна и построчная обработка на клиентской стороне, но если это можно сделать в SQL, то хотелось бы именно так.
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680404
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.всегда ли 5 это улица
Улицы в КЛАДР идут отдельной таблицей, это всегда 5-й уровень.
Вот тут найдете доку официальную:
https://www.gnivc.ru/inf_provision/classifiers_reference/kladr/

Но все зависит от того, как переложили КЛАДР на ваши структуры, к примеру, есть города-субъекты федерации, что уже дает некоторую свободу интерпретации.
А с некоторого времени КЛАДР формируется из ФИАС, в котором этих уровней... Не говоря о двух видах деления (административно-территориальное и муниципальное). Так что все, что выше улицы - вообще говоря, вопрос :)
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680407
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.В принципе в выборке будет не очень много строк (сотни, может быть тысячи), поэтому наверное возможна и построчная обработка на клиентской стороне, но если это можно сделать в SQL, то хотелось бы именно так.

Да по-всякому возможно.

Под UI проще всего идти от самого детального кода деревяшкой вверх по иерархии, собирая и затем инвертируя цепочку connect_by_root - это ежели приспичило болтаться именно иерархией (у Вас же в явном виде присутствует код КЛАДР, нафига лишние извращения-то?). Сюда же - рекурсивный with и/или, если очень хочется, латерал.
Можно функцией вида "дай мне адресную строку по коду" оформить и сбросить этот головняк.

Под пакетные операции (типа сформировать толстую пачку квитанций) проще завести "в материале" развернутую иерархию и просто на нее соединять. Только ее обновлять надо по факту обновления самого КЛАДР (если они еще вообще будут).
Выполнить можно как велосипедом, так и mat. view.
Еще вариант под пакетные задания вида "собрать клиентов по ул. Первомайской" - динамически разворачивать интересующее поддерево с материализацией во with и соединять на нее.
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680412
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousВот тут найдете доку официальную:
https://www.gnivc.ru/inf_provision/classifiers_reference/kladr/
О, спасибо.
Раньше с КЛАДР особо сталкиваться не приходилось, не знал, где искать описание.
В моей информационной системе иерархическая структура КЛАДР почти не поменялась, поэтому документация вполне применима.
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680413
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousЕще вариант под пакетные задания вида "собрать клиентов по ул. Первомайской" - динамически разворачивать интересующее поддерево с материализацией во with и соединять на нее.
Мне нужно полученную выборку сгруппировать в двухуровневую структуру, где на первом уровне будет город или населенный пункт, а на втором уровне улица и номер дома.
В явном виде код КЛАДР у меня есть в самом адресном справочнике, однако в атрибутах клиентов указанный address_id это не код КЛАДР. И напрямую получить из него код КЛАДР нельзя, нужно "подняться" хотя бы до уровня 6 (дома).
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680414
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andrey_anonymousПод UI проще всего идти от самого детального кода деревяшкой вверх по иерархии, собирая и затем инвертируя цепочку connect_by_root
А как именно это делается?
Если строить иерархию снизу вверх, то ведь у меня нет явного признака "начало цепочки".
Таким признаком может быть только наличие атрибута address_id, но при попытках перечислить их в предложении start with AO.ADDRESS_OBJECT_ID in (select address_id from ... ) запрос у меня зависает (по истечению часа так и не завершился).
Если строить иерархию сверху вниз, то начало цепочки найти будет проще, но тогда нужно строить дерево по всем адресам, которых в справочнике очень много, а затем уже полученное дерево соединять с выборкой.
...
Рейтинг: 0 / 0
Вопрос по КЛАДР
    #39680993
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.andrey_anonymousПод UI проще всего идти от самого детального кода деревяшкой вверх по иерархии, собирая и затем инвертируя цепочку connect_by_root
А как именно это делается?
Если строить иерархию снизу вверх, то ведь у меня нет явного признака "начало цепочки".
Таким признаком может быть только наличие атрибута address_id, но при попытках перечислить их в предложении start with AO.ADDRESS_OBJECT_ID in (select address_id from ... ) запрос у меня зависает (по истечению часа так и не завершился).
Под задачи UI - обычно имеется ввиду единичные поиски.
Тогда start with естественным образом формулируется как AO.ADDRESS_OBJECT_ID = ВашОбъект.address_id
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Вопрос по КЛАДР
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]