ФИАС: различия между версиями
Mavka (обсуждение | вклад) м (→Импорт данных) |
Нет описания правки |
||
(не показано 98 промежуточных версий 3 участников) | |||
Строка 2: | Строка 2: | ||
= Введение = | = Введение = | ||
<font size="6">Вопросы/пожелания/замечания - [http://gis-lab.info/forum/viewtopic.php?f=3&t=12568 форум]</font> | |||
Адреса официальной публикации: | |||
# [http://fias.nalog.ru/ Федеральная информационная адресная система] | |||
# [http://www.nalog.ru/opendata/fias_bank/ Банк данных федеральной информационной адресной системы] | |||
Оба источника предлагают идентичные данные. | |||
Федеральная информационная адресная система (ФИАС) создана Распоряжением Правительства Российской Федерации от 10.06.2011 №1011-р. С целью... | |||
Статья "[http://кладр.рф/kladr.html КЛАДР: Настоящее, прошлое и будущее]" (примерно 2004 г.) | |||
Замена КЛАДР... Тем не менее классификатор КЛАДР продолжает публиковаться и обновляться - [http://www.nalog.ru/el_usl/no_software/3776653/ версия 4.0 от 24.12.2012]. | |||
С момента первой публикации структура и содержание ФИАС многократно критиковались. Тем не менее, за время существования базы, она объективно улучшается и часть ошибок уже устранена. Поэтому указанные в этом документе несоответствия могут быть исправлены в будущем и их следует уточнять на свежих данных. | |||
//ToDo - понятие "адрес" из докум. "Перечень типовых вопросов и предложений по использованию ПО «ФИАС»" // Секретность | |||
= Загрузка данных = | = Загрузка данных = | ||
Процесс импорта данных из файлов XML в реляционную базу данных дается на примере PostgreSQL. Все применяемые инструменты являются кросплатформенными. Для других БД (MySQL, Oracle и т.п.) процедура потребует незначительной доработки. См. также гл. 2.3, в которой приводятся ссылки на сторонние проекты, предоставляющие подготовленные данные в других форматах. | |||
=== | === Создание таблиц === | ||
На сайте ФИАС представлены схемы XSD, описывающие структуру данных. Для преобразования | На сайте ФИАС представлены схемы XSD, описывающие структуру данных. Для преобразования схемы в формат SQL (CREATE TABLE...) применим XSL Transformation (XSLT). В зависимости от БД может потребоваться изменить типы данных колонок. | ||
{{Скрытый | |||
|Рамка = 1px dashed #aa0000 | |||
|Ссылка = left | |||
|Выравнивание_заголовка = left | |||
|Заголовок = Схема XSLT | |||
|Фон_заголовка = #ccccff | |||
|Содержание = | |||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
Строка 43: | Строка 64: | ||
<a>COMMENT ON COLUMN <xsl:value-of select="$filename"/>.<xsl:value-of select="@name" /> IS </a> | <a>COMMENT ON COLUMN <xsl:value-of select="$filename"/>.<xsl:value-of select="@name" /> IS </a> | ||
<xsl:choose> | <xsl:choose> | ||
<!-- Часть комментариев слишком длинная, обрезаем лишние строки --> | |||
<xsl:when test="contains(xs:annotation/xs:documentation,'
')"> | <xsl:when test="contains(xs:annotation/xs:documentation,'
')"> | ||
<a>'<xsl:value-of select="substring-before(xs:annotation/xs:documentation,'
')"/>'</a> | <a>'<xsl:value-of select="substring-before(xs:annotation/xs:documentation,'
')"/>'</a> | ||
Строка 56: | Строка 77: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
}}Схема подходит для всех таблиц ФИАС. Для работы требуется процессор, поддерживающий XSLT 2.0. Например, [http://sourceforge.net/projects/saxon/ Saxon XSLT Processor] (MPL). Тогда обработка файлов принимает вид (версии .NET, Windows): | |||
{{Скрытый | |||
|Рамка = 1px dashed #aa0000 | |||
|Ссылка = left | |||
|Выравнивание_заголовка = left | |||
|Заголовок = batch file processing | |||
|Фон_заголовка = #ccccff | |||
|Содержание = | |||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
@echo off | @echo off | ||
Строка 72: | Строка 98: | ||
) | ) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Далее полученные файлы SQL желательно откорректировать, чтобы явно назначить ключи (primary keys). | }}Далее, полученные файлы SQL желательно откорректировать, чтобы явно назначить ключи (primary keys). | ||
//// Ссылка на готовые файлы | //// Ссылка на готовые файлы | ||
Строка 80: | Строка 105: | ||
=== Импорт данных === | === Импорт данных === | ||
Для работы с большими файлами XML предпочтительнее применять потоковые парсеры. | Для работы с большими файлами XML предпочтительнее применять потоковые парсеры: используется фиксированное количество оперативной памяти (в приведенном скрипте - порядка 80 Мб) на протяжении всего процесса работы. | ||
Ниже приводится скрипт [http://scriptella.javaforge.com/ ETL Scriptella] (Apache License) на базе парсера SAX. Он подходит для любой реляционной БД, для которой есть java-драйвер. | Ниже приводится скрипт [http://scriptella.javaforge.com/ ETL Scriptella] (Apache License) на базе парсера SAX. Он подходит для любой реляционной БД, для которой есть java-драйвер. | ||
{{Скрытый | |||
|Рамка = 1px dashed #aa0000 | |||
|Ссылка = left | |||
|Выравнивание_заголовка = left | |||
|Заголовок = Скрипт для ETL Scriptella | |||
|Фон_заголовка = #ccccff | |||
|Содержание = | |||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
Строка 112: | Строка 145: | ||
DefaultHandler handler = new DefaultHandler() { | DefaultHandler handler = new DefaultHandler() { | ||
boolean isObject = false; | boolean isObject = false; | ||
int nodeCnt = 0; | |||
int recordCnt = 0; | int recordCnt = 0; | ||
public void startElement(String uri, String localName,String qName, Attributes attr) throws SAXException { | public void startElement(String uri, String localName,String qName, Attributes attr) throws SAXException { | ||
if ( | if (nodeCnt < 1) { // skip first node | ||
nodeCnt++; | |||
} else { | |||
String names = ""; | String names = ""; | ||
String values = ""; | String values = ""; | ||
Строка 146: | Строка 182: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
}}'''Примечания:''' | |||
# Паттерн ###TABLE### следует заменить на имя файла/таблицы (например, ADDROBJ); | # Паттерн ###TABLE### следует заменить на имя файла/таблицы (например, ADDROBJ); | ||
# Да работы требуются дополнительные библиотеки: [http://janino.codehaus.org/ Janino], [http://jdbc.postgresql.org/ PostgreSQL JDBC Driver]; | # Да работы требуются дополнительные библиотеки: [http://janino.codehaus.org/ Janino], [http://jdbc.postgresql.org/ PostgreSQL JDBC Driver]; | ||
# Выполняется простейшее экранирование значений (одиночная кавычка | # Выполняется простейшее экранирование значений (одиночная кавычка '). //ToDo: пустые > null | ||
== | == Другие источники == | ||
Данные ФИАС также распространяются в формате DBF. Для работы с ними рекомендуются утилиты типа [http://pgdbf.sourceforge.net/ PgDBF] ([http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=976608&msg=13347482 импорт ФИАС]). | |||
[http://code.google.com/p/rus-ref/w/list Классификаторы России (rus-ref)] | * [http://basicdata.ru/ BasicData.ru] - WebAPI и файлы для импорта в БД MySQL. Также может быть интересна БД "Почтовые отделения". | ||
* [http://code.google.com/p/rus-ref/w/list Классификаторы России (rus-ref)] | |||
* [http://zgbox.ru/articles/soft/parsing-baz-fias-v-mysql-potokovyy-xml-parser zXML Parser] - "Парсинг баз ФИАС в MySQL (потоковый XML парсер)". Программа из данных XML создает файл с sql-запросами. | |||
= Структура данных ФИАС (описание таблиц) = | = Структура данных ФИАС (описание таблиц) = | ||
Для понимания структуры данных ФИАС требуются следующие документы: | |||
# [http://fias.nalog.ru/Public/Docs/Сведения%20о%20составе%20информации%20ФИАС.doc Сведения о составе информации Федеральной информационной адресной системы] (DOC); | |||
# [http://www.nalog.ru/html/opendata/FNSR.03.1/struct03.doc Описание структуры наборов данных ФИАС] (DOC); | |||
# [http://www.nalog.ru/el_usl/no_software/3776653/ Описание Классификатора адресов российской федерации (КЛАДР)] (в архиве DOCUM.ARJ) | |||
== Таблицы == | |||
Основные | |||
* <span style="color:blue;">ADDROBJ</span> - Классификатор адресообразующих элементов (край > область > город > район > улица) | |||
* <span style="color:blue;">HOUSE</span> - Сведения по номерам домов улиц городов и населенных пунктов, номера земельных участков и т.п | |||
* <span style="color:blue;">HOUSEINT</span> - Интервалы домов | |||
* <span style="color:blue;">LANDMARK</span> - Описание мест расположения имущественных объектов | |||
* <span style="color:blue;">NORMDOC</span> - Сведения по нормативному документу, являющемуся основанием присвоения адресному элементу наименования | |||
Справочники | |||
* <span style="color:blue;">ACTSTAT</span> - Статус актуальности ФИАС | |||
* <span style="color:blue;">CENTERST</span> - Статус центра | |||
* <span style="color:blue;">CURENTST</span> - Статус актуальности КЛАДР 4.0 | |||
* <span style="color:blue;">ESTSTAT</span> - Признак владения | |||
* <span style="color:blue;">HSTSTAT</span> - Статус состояния объектов недвижимости | |||
* <span style="color:blue;">INTVSTAT</span> - Статус интервала домов | |||
* <span style="color:blue;">NDOCTYPE</span> - Тип нормативного документа (закон, приказ, справка) // ''не упоминается в официальной документации'' | |||
* <span style="color:blue;">OPERSTAT</span> - Статус действия | |||
* <span style="color:blue;">SOCRBASE</span> - Типы адресных объектов (условные сокращения и уровни подчинения) | |||
* <span style="color:blue;">STRSTAT</span> - Признак строения | |||
== ADDROBJ == | |||
=== Текстовые элементы адреса === | |||
* <span style="color:green;">OFFNAME</span> - Официальное наименование | |||
* <span style="color:green;">FORMALNAME</span> - то же что и <span style="color:green;">OFFNAME</span>, но оптимизированная для поиска | |||
* <span style="color:green;">SHORTNAME</span> - Тип объекта: обл, р-н, г, ул. Расшифровку сокращений см. по табл. <span style="color:blue;">SOCRBASE</span>. | |||
Поле <span style="color:green;">FORMALNAME</span> создано специально для поиска: из него исключены все нестандартные символы и знаки пунктуации, буква "ё" заменена на "е" и т.п. Все записи удовлетворяют запросу: | |||
<syntaxhighlight lang="tsql"> | |||
SELECT * FROM addrobj WHERE formalname !~ '[0-9А-Яа-я ]' | |||
</syntaxhighlight> | |||
=== Иерархия административных единиц === | |||
В таблице ADDROBJ иерархия построена по типу плоского дерева. И родительские и дочерние элементы хранятся в одной таблице. Воссоздание иерархии выполняется с помощью полей: | |||
* <span style="color:green;">AOGUID</span> - Глобальный уникальный идентификатор адресного объекта. Не смотря на название, уникальным в пределах таблицы он не является. Могут существовать несколько исторический версий и одна единственная актуальная для данного объекта. Подробнее см. раздел "Статус актуальности". | |||
* <span style="color:green;">PARENTGUID</span> - Идентификатор объекта родительского объекта. Содержит ссылку на <span style="color:green;">AOGUID</span> родительского элемента. | |||
* <span style="color:green;">AOLEVEL</span> - Уровень адресного объекта. Условные названия уровней (подробнее см. табл. <span style="color:blue;">SOCRBASE</span>): | |||
*: 1 - регион | |||
*: 2 - <span style="color:gray;">''зарезервирован''</span> | |||
*: 3 - район | |||
*: 4 - город | |||
*: 5 - внутригородская территория | |||
*: 6 - населенный пункт | |||
*: 7 - улицы | |||
*: 8 - <span style="color:gray;">''зарезервирован''</span> | |||
*: 90 - дополнительная территория (ГСК, СНТ, лагери отдыха и т.п.) | |||
*: 91 - улицы на дополнительной территории (улицы, линии, проезды) | |||
Получение полного адреса (от младшего к старшему): | |||
<syntaxhighlight lang="tsql"> | |||
WITH RECURSIVE child_to_parents AS ( | |||
SELECT addrobj.* FROM addrobj | |||
WHERE aoid = '51f21baa-c804-4737-9d5f-9da7a3bb1598' | |||
UNION ALL | |||
SELECT addrobj.* FROM addrobj, child_to_parents | |||
WHERE addrobj.aoguid = child_to_parents.parentguid | |||
AND addrobj.currstatus = 0 | |||
) | |||
SELECT * FROM child_to_parents ORDER BY aolevel; | |||
</syntaxhighlight> | |||
<span style="color:green;">AOLEVEL</span> отражает административно-правовое подчинение, поэтому одни и те же текстовые элементы адреса могут располагаться на разных уровнях. Например, в снт. "Волжанка" (AOLEVEL=90) улицы имеют уровень 91 (против более распространенного 7): | |||
:(1) обл. Самарская | |||
::(3) р-н Сызранский | |||
:::(90) снт Волжанка | |||
::::(91) ул. Ягодная | |||
::::(91) ул. Дачная | |||
::::(91) ул. Рябиновая | |||
Аналогично, существуют населенные пункты без улиц. Например, в пос. Лужки иерархия заканчивается на уровне 6: | |||
:(1) обл. Орловская | |||
::(3) р-н Мценский | |||
:::(6) п. Лужки | |||
Таким образом, построение таблицы полных адресов следует начинать от верхних элементов (AOLEVEL=1) к нижним (AOLEVEL=91), как правило, запрос оформляется в виде множества подзапросов (subquery). Или рекурсивно подниматься от нижних, не имеющих дочерних элементов. Рассмотрим для примера второй вариант. Поскольку число полей в обоих случаях не определено, то полный адрес будет формироваться единой строкой: | |||
{{Скрытый | |||
|Рамка = 1px dashed #aa0000 | |||
|Ссылка = left | |||
|Выравнивание_заголовка = left | |||
|Заголовок = Функция получения полного адреса (аналогично предыдущему примеру) | |||
|Фон_заголовка = #ccccff | |||
|Содержание = | |||
<syntaxhighlight lang="tsql"> | |||
DROP FUNCTION IF EXISTS make_full(text); | |||
CREATE FUNCTION make_full(IN id text, OUT fulladdress text, OUT postalcode text) AS $$ | |||
-- "id" is an unique identificator (use AOID) | |||
WITH RECURSIVE to_parents AS ( | |||
SELECT format('<addr type="%s">%s</addr>', shortname, formalname) AS fulladdress, | |||
postalcode, parentguid, aolevel | |||
FROM addrobj | |||
WHERE aoid = id | |||
UNION ALL | |||
SELECT format('<addr type="%s">%s</addr>%s', addrobj.shortname, addrobj.formalname, to_parents.fulladdress) AS fulladdress, | |||
CASE | |||
WHEN to_parents.postalcode IS NULL THEN addrobj.postalcode | |||
ELSE to_parents.postalcode | |||
END AS postalcode, | |||
addrobj.parentguid, addrobj.aolevel | |||
FROM addrobj, to_parents | |||
WHERE addrobj.aoguid = to_parents.parentguid | |||
AND addrobj.currstatus = 0 | |||
) | |||
SELECT fulladdress, postalcode FROM to_parents WHERE aolevel = 1 | |||
$$ LANGUAGE SQL; | |||
</syntaxhighlight> | |||
}}<syntaxhighlight lang="tsql"> | |||
-- сбор всех parentguid | |||
WITH all_parents AS ( | |||
SELECT DISTINCT parentguid | |||
FROM addrobj | |||
WHERE (currstatus = 0) AND (parentguid IS NOT NULL) | |||
) | |||
-- выбор элементов самого нижнего уровня (не входящих в список all_parents) | |||
-- и получение полного адреса | |||
SELECT (make_full(aoid)).* | |||
FROM addrobj | |||
WHERE (currstatus = 0) AND (aoguid NOT IN (SELECT parentguid FROM all_parents)) | |||
</syntaxhighlight> | |||
Образцы результатов: | |||
<syntaxhighlight lang="xml"> | |||
<addr type="обл">Волгоградская</addr> <addr type="г">Волгоград</addr> <addr type="ул">Лавровая</addr> | |||
<addr type="обл">Орловская</addr> <addr type="р-н">Мценский</addr> <addr type="п">Лужки</addr> | |||
<addr type="обл">Челябинская</addr> <addr type="г">Челябинск</addr> <addr type="ул">Балтийская</addr> | |||
<addr type="край">Приморский</addr> <addr type="г">Артем</addr> <addr type="ул">Григорьева</addr> | |||
<addr type="обл">Калужская</addr> <addr type="р-н">Ульяновский</addr> <addr type="д">Бродок</addr> | |||
<addr type="обл">Свердловская</addr> <addr type="г">Екатеринбург</addr> <addr type="ул">Окраинная</addr> | |||
<addr type="Респ">Тыва</addr> <addr type="р-н">Чаа-Хольский</addr> <addr type="м">Сесеге</addr> | |||
</syntaxhighlight> | |||
'''Примечания:''' | |||
# На настоящий момент существует 10 уровней (<span style="color:green;">AOLEVEL</span>). Но могут быть введены дополнительные. Например, ранее все ГСК и СНТ вносились на уровень 7 (улицы). Позднее, для них был выделен уровень 90 (дополнительные территории). | |||
# На зарезервированных уровнях (2 и 8) не содержится записей, в том числе и исторических. | |||
=== Статус актуальности === | |||
Из базы ФИАС почти никогда не удаляются элементы. Они могут быть только переведены в разряд "отключенных" (устаревшие, измененные и т.п.), что аналогично работе КЛАДР. | |||
:Примечание. Но информация о некоторых адресных объектах всё же может удаляться из БД ФИАС. См документ [http://fias.nalog.ru/Public/Docs/%D0%A1%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BE%20%D1%81%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%B5%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%B8%20%D0%A4%D0%98%D0%90%D0%A1.doc СВЕДЕНИЯ О СОСТАВЕ ИНФОРМАЦИИ ФЕДЕРАЛЬНОЙ ИНФОРМАЦИОННОЙ АДРЕСНОЙ СИСТЕМЫ], цитирую: | |||
::"Технологически удалённые из БД ФИАС записи с адресными сведениями... включают удалённые администратором ФИАС по заявке операторов ФИАС (ошибочно введённые, дубли адресных сведений) адресные сведения". | |||
:Т.е. дубли и ошибочно введённые данные могут быть физически удалены. Большинство из них приобретают статус актуальности КЛАДР (CURRSTATUS) равный 99, т.е. "несуществующий", а после этого уже становятся "технологически удалёнными". Если их нужно найти, то надо скачать т.н. "дельты данных", которые используются для обновления БД ФИАС, это архивы fias_delta_dbf.rar на сайте [http://fias.nalog.ru/Public/DownloadPage.aspx ФИАС]. В некоторых из них имеются таблицы DADDROBJ, DHOUSE, и пр., содержащие технологически удалённые записи, попавшие в "дельту". На дату 15.12.2014 всего технологически удалено 793 записи, из них: 363 актуальных (т.е. ACTSTATUS = 1), 1 с CURRSTATUS != 99, и 1 с LIVESTATUS = 1. | |||
Рассмотрим поля, определяющие действительность объекта: | |||
Для выбора актуальных записей рекомендуется ориентироваться на поля <span style="color:green;">CURRSTATUS</span> и <span style="color:green;">LIVESTATUS</span>. | |||
Рассмотрим подробнее: | |||
* <span style="color:green;">LIVESTATUS</span> - Признак действующего адресного объекта. Принимает значения: 0 - не действующий, 1 - действующий (см. прим. 1). | |||
* <span style="color:green;">CURRSTATUS</span> - Статус актуальности КЛАДР 4. Принимает значения: 0 - актуальный, 1-50 - исторический, 51 - переподчиненный (см. табл. <span style="color:blue;">CURENTST</span> и гл. 1.2. "Коды адресных объектов" документации КЛАДР). | |||
* <span style="color:green;">OPERSTATUS</span> - Статус действия. Принимает значения: 1 - Инициация, 10 - Добавление, 20 - Изменение и др (см. табл. <span style="color:blue;">OPERSTAT</span>). | |||
* <span style="color:green;">ACTSTATUS</span> - Статус актуальности адресного объекта ФИАС. Принимает значения: 1 - актуальный, 0 – не актуальный (см. табл. <span style="color:blue;">ACTSTAT</span>). Отвечает непосредственно за актуальность "имени". Если объект был переименован (чаще это исправление опечаток), то старая запись получает CURRSTATUS=1 и ACTSTATUS=0. Если же административная единица была ликвидирована или переподчинена, то имя останется по-прежнему актуальным: CURRSTATUS=99/51 и ACTSTATUS=1. В тоже время, при внесении изменений, не касающихся непосредственно адресной части, признак актуальности все равно сбрасывается (ACTSTATUS=0). | |||
Также, в категорию актуальности можно отнести поля <span style="color:green;">STARTDATE</span>, <span style="color:green;">ENDDATE</span>, <span style="color:green;">UPDATEDATE</span>. Но, на данный момент (декабрь 2012 г.) значения этих полей редко бывают заполнены правильно. | |||
Покажем на примере выбор актуальных и исторический записей. "Пермский край" был образован 01.12.2005 объединением "Пермской области" и "Коми-Пермяцкого АО". В базе ФИАС это отразилось следующим образом (см. табл. 1): | |||
# Создана новая запись "Пермский край" (1-й столбец); | |||
# Запись "Пермская область" (2-й столбец) сохранена, причем <span style="color:green;">AOGUID</span> обеих записей идентичен (для связи с дочерними объектами); | |||
# Запись "Коми-Пермяцкий АО" (3-й столбец) также сохранена. | |||
'''Таблица 1''' | |||
{| {{table}} cellspacing="0" border="1" | |||
| align="center" style="background:#f0f0f0;"|'''Примечание''' | |||
| align="center" style="background:#f0f0f0;"|'''Актуальная запись''' | |||
| align="center" style="background:#f0f0f0;"|'''Пермская обл.''' | |||
| align="center" style="background:#f0f0f0;"|'''Коми-Пермяцкий АО''' | |||
|- | |||
| AOID||c685f6ca-d7e1-4938-8b21-7c20035652d2||744e2599-d2bb-4364-9922-c13febb16e81||68824dc3-da0f-42d3-bd0b-1ceb91ff27bf | |||
|- | |||
| AOGUID||4f8b1a21-e4bb-422f-9087-d3cbf4bebc14||4f8b1a21-e4bb-422f-9087-d3cbf4bebc14||e3d95b95-cc2d-440d-95c6-65577fae076e | |||
|- | |||
| AOLEVEL||1||1||1 | |||
|- | |||
| PREVID||744e2599-d2bb-4364-9922-c13febb16e81||68824dc3-da0f-42d3-bd0b-1ceb91ff27bf|| | |||
|- | |||
| NEXTID||||c685f6ca-d7e1-4938-8b21-7c20035652d2||744e2599-d2bb-4364-9922-c13febb16e81 | |||
|- | |||
| ACTSTATUS||1||0||1 | |||
|- | |||
| OPERSTATUS||1||1||1 | |||
|- | |||
| CURRSTATUS||0||1||51 | |||
|- | |||
| LIVESTATUS||1||0||0 | |||
|- | |||
| UPDATEDATE||2011-09-13||2011-09-13||2011-09-13 | |||
|- | |||
| STARTDATE||1900-01-01||1900-01-01||1900-01-01 | |||
|- | |||
| ENDDATE||2079-06-06||2079-06-06||2079-06-06 | |||
|- | |||
| FORMALNAME||Пермский||Пермская||Коми-Пермяцкий | |||
|- | |||
| OFFNAME||Пермский||Пермская||Коми-Пермяцкий | |||
|- | |||
| SHORTNAME||край||обл||АО | |||
|} | |||
Значения полей: | |||
# <span style="color:green;">ACTSTATUS</span> для Коми-Пермяцкого АО сохранен в значении "Актуальный"; | |||
# <span style="color:green;">OPERSTATUS</span> не изменился - ошибочно(?); | |||
# <span style="color:green;">CURRSTATUS</span> правильный (0 - актуальный, 1 - исторический, 51 - переподчиненный); | |||
# <span style="color:green;">LIVESTATUS</span> показывает единственную актуальную запись, но значения инвертированы (см. прим. 1). | |||
//ToDo - изменения в подчиненных объектах | |||
'''Примечания:''' | |||
# Все актуальные записи (CURRSTATUS = 0) имеют значение (LIVESTATUS = 1) и наоборот. Очевидно, что поведение <span style="color:green;">LIVESTATUS</span> не соответствует описанному в документации. Поле можно использовать для выбора актуальных записей, но с осторожностью до выяснения ситуации в будущем. | |||
=== Исторические названия === | |||
Поля <span style="color:green;">AOID</span>, <span style="color:green;">PREVID</span>, <span style="color:green;">NEXTID</span> в совокупности составляют цепочку от современного к устаревшим наименованиям объекта. Хотя, если имеется два прямых предка (как в примере про "Пермский край"), то наследование невозможно отразить полностью однозначно. | |||
В общем виде получение исторических вариантов наименований объекта имеет вид: | |||
<syntaxhighlight lang="tsql"> | |||
WITH RECURSIVE old_names AS ( | |||
SELECT * | |||
FROM addrobj | |||
-- вариации отдельной записи: | |||
WHERE aoid = '002ff6b9-c2db-46e5-99da-8cf30d239b27' | |||
-- полный список: | |||
-- WHERE currstatus = 0 AND previd IS NOT NULL | |||
UNION | |||
SELECT addrobj.* | |||
FROM old_names, addrobj | |||
WHERE (addrobj.nextid = old_names.aoid) | |||
) | |||
SELECT * FROM old_names | |||
</syntaxhighlight> | |||
Примеры: | |||
{| {{table}} border="1" cellspacing="0" style="text-align: center;" | |||
| align="center" style="background:#f0f0f0;"|'''shortname''' | |||
| align="center" style="background:#f0f0f0;"|'''formalname''' | |||
| align="center" style="background:#f0f0f0;"|'''actstatus''' | |||
| align="center" style="background:#f0f0f0;"|'''operstatus''' | |||
| align="center" style="background:#f0f0f0;"|'''currstatus''' | |||
| align="center" style="background:#f0f0f0;"|'''livestatus''' | |||
| align="center" style="background:#f0f0f0;"|'''updatedate''' | |||
| align="center" style="background:#f0f0f0;"|'''startdate''' | |||
| align="center" style="background:#f0f0f0;"|'''enddate''' | |||
|- | |||
| д||Малое Пермиево||1||21||0||1||2012-09-08||2012-02-01||2079-06-06 | |||
|- | |||
| д||Малое Пермиево||0||1||2||0||2011-09-14||1900-01-01||2012-02-01 | |||
|- | |||
| с||Малое Пермиево||0||1||1||0||2011-09-14||1900-01-01||2079-06-06 | |||
|- | |||
| colspan="9" | ... | |||
|- | |||
| ул||Подстанция 220||1||20||0||1||2012-03-12||1911-11-11||2079-06-06 | |||
|- | |||
| ул||Подстанция (Комиссарово)||0||1||1||0||2011-09-15||1900-01-01||1911-11-11 | |||
|- | |||
| colspan="9" | ... | |||
|- | |||
| пер||Рябиновый||1||20||0||1||2011-09-27||1900-01-01||2079-06-06 | |||
|- | |||
| ул||Рябиновая||0||1||1||0||2011-09-15||1900-01-01||2079-06-06 | |||
|- | |||
| colspan="9" | ... | |||
|- | |||
| снт||Восход(п.Селезнево)||1||1||0||1||2011-09-14||1900-01-01||2079-06-06 | |||
|- | |||
| дп||СТ Восход(п.Селезнево)||0||1||1||0||2011-09-14||1900-01-01||2079-06-06 | |||
|- | |||
| colspan="9" | ... | |||
|- | |||
| ул||Самбуева В.М.||1||1||0||1||2011-09-14||1900-01-01||2079-06-06 | |||
|- | |||
| ул||Ф.Энгельса||0||1||1||0||2011-09-14||1900-01-01||2079-06-06 | |||
|- | |||
| colspan="9" | ... | |||
|- | |||
| проезд||3-й Лабинский||1||1||0||1||2011-09-14||1900-01-01||2079-06-06 | |||
|- | |||
| ул||Лабинская 2-я||0||1||1||0||2011-09-14||1900-01-01||2079-06-06 | |||
|} | |||
// ToDo: | |||
'''Примечания:''' | |||
# Наблюдение (в документации не разъяснено): при внесении изменений, предыдущая историческая запись получает значение (CURRSTATUS = 1). Если вносится повторное изменение, то аннулируемая запись принимает значение (CURRSTATUS = 2). Таким образом, цепочка от современного названия к самому старому принимает вид: актуальное (0), предыдущее (3), более раннее (2), самое старое (1). | |||
=== Адресные классификаторы === | |||
Записи в БД ФИАС содержат ссылки на другие российские адресные классификаторы: | |||
* <span style="color:green;">OKATO</span> - код объекта административно-территориального деления (ОКАТО) | |||
* <span style="color:green;">OKTMO</span> - код муниципального образования (ОКТМО) | |||
* <span style="color:green;">CODE</span> - код КЛАДР | |||
* <span style="color:green;">PLAINCODE</span> - код КЛАДР без признака актуальности (последних двух цифр), см. также <span style="color:green;">CURRSTATUS</span> | |||
ФИАС предлагает собственный "классификационный код", который хранится, разбитым на отдельные элементы: <span style="color:green;">REGIONCODE</span>, <span style="color:green;">AUTOCODE</span>, <span style="color:green;">AREACODE</span>, <span style="color:green;">CITYCODE</span>, <span style="color:green;">CTARCODE</span>, <span style="color:green;">PLACECODE</span>, <span style="color:green;">STREETCODE</span>, <span style="color:green;">EXTRCODE</span>, <span style="color:green;">SEXTCODE</span>. | |||
В целом, код является расширенным вариантом КЛАДР: | |||
СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ | |||
ФИАС: 74 0 026 000 000 032 0021 0000 000 | |||
КЛАДР: 74 026 000 032 0021 | |||
Другой пример: | |||
СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ | |||
ФИАС: 33 0 003 001 000 000 0000 0303 000, "Владимирская обл, Вязниковский р-н, г Вязники, снт Коллективный сад Рябинушка-1" | |||
КЛАДР: 33 003 001 000 0303 | |||
Могут быть случаи, когда адресному объекту в БД ФИАС не соответствует никакой КЛАДР-код, например: | |||
СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ | |||
ФИАС: 23 0 000 002 000 000 0000 0383 009, "Краснодарский край, г Армавир, мкр Северный жилой район микрорайон 8, ул Спортивная" | |||
Подробное описание см. в документе "Сведения о составе информации Федеральной информационной адресной системы". | |||
=== Прочие поля === | |||
* Ведомственные классификаторы ФНС России: СОНО - <span style="color:green;">IFNSFL</span>, <span style="color:green;">IFNSUL</span>; СОУН - <span style="color:green;">TERRIFNSFL</span>, <span style="color:green;">TERRIFNSUL</span>. | |||
* <span style="color:green;">CENTSTATUS</span> - статус центра; ненулевое значение присвоено столицам, административным центрам и центральным районам регионов (подробнее см. табл. <span style="color:blue;">CENTERST</span>). | |||
* <span style="color:green;">NORMDOC</span> - нормативный документ (табл. <span style="color:blue;">NORMDOC</span>). | |||
= Обновление БД ФИАС = | |||
Привожу текст из документа [http://fias.nalog.ru/Public/Docs/%D0%A1%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BE%20%D1%81%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%B5%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D0%B8%20%D0%A4%D0%98%D0%90%D0%A1.doc СВЕДЕНИЯ О СОСТАВЕ ИНФОРМАЦИИ ФЕДЕРАЛЬНОЙ ИНФОРМАЦИОННОЙ АДРЕСНОЙ СИСТЕМЫ]. | |||
:На портал ФИАС выгружаются актуальные и исторические сведения ФИАС, а так же технологически удалённые из БД ФИАС адресные сведения. | |||
:Актуальные и исторические сведения ФИАС выгружается в виде файлов (таблиц) DBF и файлов XML. | |||
:Вместе с полной базой ФИАС выгружаются дельта данные – новые, изменившиеся и удаленные данные с момента предыдущей выгрузки базы. | |||
:Дельта данные, т.е. новые, изменившиеся и удаленные данные появившиеся с момента предыдущей выгрузки базы ФИАС, загружаются по следующему алгоритму: по наличию или отсутствию ключа в пользовательской базе определяется тип операции – добавление или обновление записи. После проведения соответствующих операций необходимо удалить по ключу записи, присутствующие в таблицах технологически удаленных данных. | |||
Наличие таких "дельт" позволяет быстро обновить БД ФИАС, не скачивая полный архив (на 2014.12.01 его размер составляет 1.8 Гб). Алгоритм обнобления, действительно, довольно прост. Привожу текст процедуры обновления для MySQL на примере таблицы ADDROBJ: | |||
<syntaxhighlight lang="tsql"> | |||
-- предположим, что дельту "залили" в схему "delta", а обновляемый ФИАС находится в схеме "fias" | |||
use delta; | |||
update | |||
fias.ADDROBJ f | |||
inner join ADDROBJ d on d.AOID = f.AOID | |||
set | |||
f.actstatus=d.actstatus,f.aoguid=d.aoguid,f.aoid=d.aoid,f.aolevel=d.aolevel,f.areacode=d.areacode,f.autocode=d.autocode,f.centstatus=d.centstatus,f.citycode=d.citycode,f.code=d.code,f.currstatus=d.currstatus,f.enddate=d.enddate,f.formalname=d.formalname,f.ifnsfl=d.ifnsfl,f.ifnsul=d.ifnsul,f.nextid=d.nextid,f.offname=d.offname,f.okato=d.okato,f.oktmo=d.oktmo,f.operstatus=d.operstatus,f.parentguid=d.parentguid,f.placecode=d.placecode,f.plaincode=d.plaincode,f.postalcode=d.postalcode,f.previd=d.previd,f.regioncode=d.regioncode,f.shortname=d.shortname,f.startdate=d.startdate,f.streetcode=d.streetcode,f.ctarcode=d.ctarcode,f.extrcode=d.extrcode,f.sextcode=d.sextcode,f.livestatus=d.livestatus,f.normdoc=d.normdoc,f.terrifnsfl=d.terrifnsfl,f.terrifnsul=d.terrifnsul,f.updatedate=d.updatedate; | |||
insert into fias.ADDROBJ (actstatus,aoguid,aoid,aolevel,areacode,autocode,centstatus,citycode,code,currstatus,enddate,formalname,ifnsfl,ifnsul,nextid,offname,okato,oktmo,operstatus,parentguid,placecode,plaincode,postalcode,previd,regioncode,shortname,startdate,streetcode,ctarcode,extrcode,sextcode,livestatus,normdoc,terrifnsfl,terrifnsul,updatedate) | |||
select | |||
d.actstatus,d.aoguid,d.aoid,d.aolevel,d.areacode,d.autocode,d.centstatus,d.citycode,d.code,d.currstatus,d.enddate,d.formalname,d.ifnsfl,d.ifnsul,d.nextid,d.offname,d.okato,d.oktmo,d.operstatus,d.parentguid,d.placecode,d.plaincode,d.postalcode,d.previd,d.regioncode,d.shortname,d.startdate,d.streetcode,d.ctarcode,d.extrcode,d.sextcode,d.livestatus,d.normdoc,d.terrifnsfl,d.terrifnsul,d.updatedate | |||
from | |||
ADDROBJ d | |||
left join fias.ADDROBJ f on d.AOID = f.AOID | |||
where f.AOID is null; | |||
delete from fias.ADDROBJ where aoid in (select aoid from DADDROBJ); | |||
</syntaxhighlight> | |||
Иногда может изменятся структура самих таблиц, что требует ручного контроля. Например, колонка "oktmo" сначала содержала 8 символов, а потом была расширена до 11 символов. | |||
Тем не менне, несмотря на удобство обновления через дельты, я рекомендую для обновления заменять БД ФИАС целиком (а после этого объединять её с таблицами технологически удалённых данных, при необходимости). Дело в том, что дельты могут содержать неполную информацию, проще говоря oldfias + delta != newfias. Например, я обновлял БД ФИАС от 2012.07.01 через дельты до состояния на 2012.09.24. Если в дельте была информация о переподчинении или об изменении адресного объекта, то предыдущая версия адресного объекта не обновлялась, т.е. не проставлялось (NEXTID = ид_нового, LIVESTATUS = 0, ACTSTATUS = 0). В результате в БД ФИАС были объекты с одинаковым AOGUID, но имеющие ACTSTATUS = 1. Некоторые новые данные просто отсутствовали в дельте. Возможно, что разработчики ФИАС уже исправили эти ошибки, и более свежие дельты следующие за 2012.09.24 содержат полную информацию, но это требует проверки. | |||
= Ошибки БД ФИАС = | |||
БД ФИАС может содержать ошибки в данных, а) связанные с нарушением целостности двунаправленных списков PREVID/NEXTID, б) ошибки, когда запись об адресном объекте имеет OPERSTATUS = 1, а в действительности произошла другая операция (переименование, переподчинение, слияние, или дробление), и в) ошибки, когда отсутствуют исторические сведения (вызванные тем, что администраторы БД ФИАС, видимо, выполняли прямое изменение данных с помощью SQL-запросов). | |||
Для иллюстрации можно открыть портал ФИАС и воспользоваться [http://fias.nalog.ru/Public/SearchPage.aspx?SearchState=2 расширенным поиском]. В поле "Регион" введите "Санкт-Петербург город", в поле "Уровень" выберите "Регион". Нажмите "Найти". Если просмотреть историю изменения города Санкт-Петербург, то можно обнаружить, что Санкт-Петербург раньше назывался "станция Володарская", а должно быть "Ленинград". Это иллюстрирует нарушение целостности двунаправленных списков. | |||
Для иллюстрации ситуации, когда отсутствуют исторические сведения можно рассмотреть адресный объект с AOGUID="df84b14c-6006-46d1-8ce3-3a6ddf8643bd". В БД ФИАС от 2012.08.06 этот объект имел КЛАДР код равный 24000001101000100. В какой-то момент произошло переподчинение родительского объекта, и в итоге у него изменился уровень AOLEVEL с 6 на 90. Соответственно, уровень AOLEVEL дочернего объекта изменился с 7 на 91. Если взять БД ФИАС от 2014.12.01, то в ней нельзя обнаружить исторической записи с КЛАДР кодом равным 24000001101000100. Нет этой записи и в таблицах DADDROBJ. | |||
Ошибки с неправильным OPERSTATUS слишком многочисленны, их классифицирование выходит за рамки данной статьи. |
Текущая версия от 18:41, 24 декабря 2014
Введение
Вопросы/пожелания/замечания - форум
Адреса официальной публикации:
Оба источника предлагают идентичные данные.
Федеральная информационная адресная система (ФИАС) создана Распоряжением Правительства Российской Федерации от 10.06.2011 №1011-р. С целью...
Статья "КЛАДР: Настоящее, прошлое и будущее" (примерно 2004 г.)
Замена КЛАДР... Тем не менее классификатор КЛАДР продолжает публиковаться и обновляться - версия 4.0 от 24.12.2012.
С момента первой публикации структура и содержание ФИАС многократно критиковались. Тем не менее, за время существования базы, она объективно улучшается и часть ошибок уже устранена. Поэтому указанные в этом документе несоответствия могут быть исправлены в будущем и их следует уточнять на свежих данных.
//ToDo - понятие "адрес" из докум. "Перечень типовых вопросов и предложений по использованию ПО «ФИАС»" // Секретность
Загрузка данных
Процесс импорта данных из файлов XML в реляционную базу данных дается на примере PostgreSQL. Все применяемые инструменты являются кросплатформенными. Для других БД (MySQL, Oracle и т.п.) процедура потребует незначительной доработки. См. также гл. 2.3, в которой приводятся ссылки на сторонние проекты, предоставляющие подготовленные данные в других форматах.
Создание таблиц
На сайте ФИАС представлены схемы XSD, описывающие структуру данных. Для преобразования схемы в формат SQL (CREATE TABLE...) применим XSL Transformation (XSLT). В зависимости от БД может потребоваться изменить типы данных колонок.
Схема подходит для всех таблиц ФИАС. Для работы требуется процессор, поддерживающий XSLT 2.0. Например, Saxon XSLT Processor (MPL). Тогда обработка файлов принимает вид (версии .NET, Windows):
Далее, полученные файлы SQL желательно откорректировать, чтобы явно назначить ключи (primary keys).
//// Ссылка на готовые файлы
Импорт данных
Для работы с большими файлами XML предпочтительнее применять потоковые парсеры: используется фиксированное количество оперативной памяти (в приведенном скрипте - порядка 80 Мб) на протяжении всего процесса работы.
Ниже приводится скрипт ETL Scriptella (Apache License) на базе парсера SAX. Он подходит для любой реляционной БД, для которой есть java-драйвер.
Примечания:
- Паттерн ###TABLE### следует заменить на имя файла/таблицы (например, ADDROBJ);
- Да работы требуются дополнительные библиотеки: Janino, PostgreSQL JDBC Driver;
- Выполняется простейшее экранирование значений (одиночная кавычка '). //ToDo: пустые > null
Другие источники
Данные ФИАС также распространяются в формате DBF. Для работы с ними рекомендуются утилиты типа PgDBF (импорт ФИАС).
- BasicData.ru - WebAPI и файлы для импорта в БД MySQL. Также может быть интересна БД "Почтовые отделения".
- Классификаторы России (rus-ref)
- zXML Parser - "Парсинг баз ФИАС в MySQL (потоковый XML парсер)". Программа из данных XML создает файл с sql-запросами.
Структура данных ФИАС (описание таблиц)
Для понимания структуры данных ФИАС требуются следующие документы:
- Сведения о составе информации Федеральной информационной адресной системы (DOC);
- Описание структуры наборов данных ФИАС (DOC);
- Описание Классификатора адресов российской федерации (КЛАДР) (в архиве DOCUM.ARJ)
Таблицы
Основные
- ADDROBJ - Классификатор адресообразующих элементов (край > область > город > район > улица)
- HOUSE - Сведения по номерам домов улиц городов и населенных пунктов, номера земельных участков и т.п
- HOUSEINT - Интервалы домов
- LANDMARK - Описание мест расположения имущественных объектов
- NORMDOC - Сведения по нормативному документу, являющемуся основанием присвоения адресному элементу наименования
Справочники
- ACTSTAT - Статус актуальности ФИАС
- CENTERST - Статус центра
- CURENTST - Статус актуальности КЛАДР 4.0
- ESTSTAT - Признак владения
- HSTSTAT - Статус состояния объектов недвижимости
- INTVSTAT - Статус интервала домов
- NDOCTYPE - Тип нормативного документа (закон, приказ, справка) // не упоминается в официальной документации
- OPERSTAT - Статус действия
- SOCRBASE - Типы адресных объектов (условные сокращения и уровни подчинения)
- STRSTAT - Признак строения
ADDROBJ
Текстовые элементы адреса
- OFFNAME - Официальное наименование
- FORMALNAME - то же что и OFFNAME, но оптимизированная для поиска
- SHORTNAME - Тип объекта: обл, р-н, г, ул. Расшифровку сокращений см. по табл. SOCRBASE.
Поле FORMALNAME создано специально для поиска: из него исключены все нестандартные символы и знаки пунктуации, буква "ё" заменена на "е" и т.п. Все записи удовлетворяют запросу:
SELECT * FROM addrobj WHERE formalname !~ '[0-9А-Яа-я ]'
Иерархия административных единиц
В таблице ADDROBJ иерархия построена по типу плоского дерева. И родительские и дочерние элементы хранятся в одной таблице. Воссоздание иерархии выполняется с помощью полей:
- AOGUID - Глобальный уникальный идентификатор адресного объекта. Не смотря на название, уникальным в пределах таблицы он не является. Могут существовать несколько исторический версий и одна единственная актуальная для данного объекта. Подробнее см. раздел "Статус актуальности".
- PARENTGUID - Идентификатор объекта родительского объекта. Содержит ссылку на AOGUID родительского элемента.
- AOLEVEL - Уровень адресного объекта. Условные названия уровней (подробнее см. табл. SOCRBASE):
- 1 - регион
- 2 - зарезервирован
- 3 - район
- 4 - город
- 5 - внутригородская территория
- 6 - населенный пункт
- 7 - улицы
- 8 - зарезервирован
- 90 - дополнительная территория (ГСК, СНТ, лагери отдыха и т.п.)
- 91 - улицы на дополнительной территории (улицы, линии, проезды)
Получение полного адреса (от младшего к старшему):
WITH RECURSIVE child_to_parents AS (
SELECT addrobj.* FROM addrobj
WHERE aoid = '51f21baa-c804-4737-9d5f-9da7a3bb1598'
UNION ALL
SELECT addrobj.* FROM addrobj, child_to_parents
WHERE addrobj.aoguid = child_to_parents.parentguid
AND addrobj.currstatus = 0
)
SELECT * FROM child_to_parents ORDER BY aolevel;
AOLEVEL отражает административно-правовое подчинение, поэтому одни и те же текстовые элементы адреса могут располагаться на разных уровнях. Например, в снт. "Волжанка" (AOLEVEL=90) улицы имеют уровень 91 (против более распространенного 7):
- (1) обл. Самарская
- (3) р-н Сызранский
- (90) снт Волжанка
- (91) ул. Ягодная
- (91) ул. Дачная
- (91) ул. Рябиновая
- (90) снт Волжанка
- (3) р-н Сызранский
Аналогично, существуют населенные пункты без улиц. Например, в пос. Лужки иерархия заканчивается на уровне 6:
- (1) обл. Орловская
- (3) р-н Мценский
- (6) п. Лужки
- (3) р-н Мценский
Таким образом, построение таблицы полных адресов следует начинать от верхних элементов (AOLEVEL=1) к нижним (AOLEVEL=91), как правило, запрос оформляется в виде множества подзапросов (subquery). Или рекурсивно подниматься от нижних, не имеющих дочерних элементов. Рассмотрим для примера второй вариант. Поскольку число полей в обоих случаях не определено, то полный адрес будет формироваться единой строкой:
-- сбор всех parentguid
WITH all_parents AS (
SELECT DISTINCT parentguid
FROM addrobj
WHERE (currstatus = 0) AND (parentguid IS NOT NULL)
)
-- выбор элементов самого нижнего уровня (не входящих в список all_parents)
-- и получение полного адреса
SELECT (make_full(aoid)).*
FROM addrobj
WHERE (currstatus = 0) AND (aoguid NOT IN (SELECT parentguid FROM all_parents))
Образцы результатов:
<addr type="обл">Волгоградская</addr> <addr type="г">Волгоград</addr> <addr type="ул">Лавровая</addr>
<addr type="обл">Орловская</addr> <addr type="р-н">Мценский</addr> <addr type="п">Лужки</addr>
<addr type="обл">Челябинская</addr> <addr type="г">Челябинск</addr> <addr type="ул">Балтийская</addr>
<addr type="край">Приморский</addr> <addr type="г">Артем</addr> <addr type="ул">Григорьева</addr>
<addr type="обл">Калужская</addr> <addr type="р-н">Ульяновский</addr> <addr type="д">Бродок</addr>
<addr type="обл">Свердловская</addr> <addr type="г">Екатеринбург</addr> <addr type="ул">Окраинная</addr>
<addr type="Респ">Тыва</addr> <addr type="р-н">Чаа-Хольский</addr> <addr type="м">Сесеге</addr>
Примечания:
- На настоящий момент существует 10 уровней (AOLEVEL). Но могут быть введены дополнительные. Например, ранее все ГСК и СНТ вносились на уровень 7 (улицы). Позднее, для них был выделен уровень 90 (дополнительные территории).
- На зарезервированных уровнях (2 и 8) не содержится записей, в том числе и исторических.
Статус актуальности
Из базы ФИАС почти никогда не удаляются элементы. Они могут быть только переведены в разряд "отключенных" (устаревшие, измененные и т.п.), что аналогично работе КЛАДР.
- Примечание. Но информация о некоторых адресных объектах всё же может удаляться из БД ФИАС. См документ СВЕДЕНИЯ О СОСТАВЕ ИНФОРМАЦИИ ФЕДЕРАЛЬНОЙ ИНФОРМАЦИОННОЙ АДРЕСНОЙ СИСТЕМЫ, цитирую:
- "Технологически удалённые из БД ФИАС записи с адресными сведениями... включают удалённые администратором ФИАС по заявке операторов ФИАС (ошибочно введённые, дубли адресных сведений) адресные сведения".
- Т.е. дубли и ошибочно введённые данные могут быть физически удалены. Большинство из них приобретают статус актуальности КЛАДР (CURRSTATUS) равный 99, т.е. "несуществующий", а после этого уже становятся "технологически удалёнными". Если их нужно найти, то надо скачать т.н. "дельты данных", которые используются для обновления БД ФИАС, это архивы fias_delta_dbf.rar на сайте ФИАС. В некоторых из них имеются таблицы DADDROBJ, DHOUSE, и пр., содержащие технологически удалённые записи, попавшие в "дельту". На дату 15.12.2014 всего технологически удалено 793 записи, из них: 363 актуальных (т.е. ACTSTATUS = 1), 1 с CURRSTATUS != 99, и 1 с LIVESTATUS = 1.
Рассмотрим поля, определяющие действительность объекта:
Для выбора актуальных записей рекомендуется ориентироваться на поля CURRSTATUS и LIVESTATUS.
Рассмотрим подробнее:
- LIVESTATUS - Признак действующего адресного объекта. Принимает значения: 0 - не действующий, 1 - действующий (см. прим. 1).
- CURRSTATUS - Статус актуальности КЛАДР 4. Принимает значения: 0 - актуальный, 1-50 - исторический, 51 - переподчиненный (см. табл. CURENTST и гл. 1.2. "Коды адресных объектов" документации КЛАДР).
- OPERSTATUS - Статус действия. Принимает значения: 1 - Инициация, 10 - Добавление, 20 - Изменение и др (см. табл. OPERSTAT).
- ACTSTATUS - Статус актуальности адресного объекта ФИАС. Принимает значения: 1 - актуальный, 0 – не актуальный (см. табл. ACTSTAT). Отвечает непосредственно за актуальность "имени". Если объект был переименован (чаще это исправление опечаток), то старая запись получает CURRSTATUS=1 и ACTSTATUS=0. Если же административная единица была ликвидирована или переподчинена, то имя останется по-прежнему актуальным: CURRSTATUS=99/51 и ACTSTATUS=1. В тоже время, при внесении изменений, не касающихся непосредственно адресной части, признак актуальности все равно сбрасывается (ACTSTATUS=0).
Также, в категорию актуальности можно отнести поля STARTDATE, ENDDATE, UPDATEDATE. Но, на данный момент (декабрь 2012 г.) значения этих полей редко бывают заполнены правильно.
Покажем на примере выбор актуальных и исторический записей. "Пермский край" был образован 01.12.2005 объединением "Пермской области" и "Коми-Пермяцкого АО". В базе ФИАС это отразилось следующим образом (см. табл. 1):
- Создана новая запись "Пермский край" (1-й столбец);
- Запись "Пермская область" (2-й столбец) сохранена, причем AOGUID обеих записей идентичен (для связи с дочерними объектами);
- Запись "Коми-Пермяцкий АО" (3-й столбец) также сохранена.
Таблица 1
Примечание | Актуальная запись | Пермская обл. | Коми-Пермяцкий АО |
AOID | c685f6ca-d7e1-4938-8b21-7c20035652d2 | 744e2599-d2bb-4364-9922-c13febb16e81 | 68824dc3-da0f-42d3-bd0b-1ceb91ff27bf |
AOGUID | 4f8b1a21-e4bb-422f-9087-d3cbf4bebc14 | 4f8b1a21-e4bb-422f-9087-d3cbf4bebc14 | e3d95b95-cc2d-440d-95c6-65577fae076e |
AOLEVEL | 1 | 1 | 1 |
PREVID | 744e2599-d2bb-4364-9922-c13febb16e81 | 68824dc3-da0f-42d3-bd0b-1ceb91ff27bf | |
NEXTID | c685f6ca-d7e1-4938-8b21-7c20035652d2 | 744e2599-d2bb-4364-9922-c13febb16e81 | |
ACTSTATUS | 1 | 0 | 1 |
OPERSTATUS | 1 | 1 | 1 |
CURRSTATUS | 0 | 1 | 51 |
LIVESTATUS | 1 | 0 | 0 |
UPDATEDATE | 2011-09-13 | 2011-09-13 | 2011-09-13 |
STARTDATE | 1900-01-01 | 1900-01-01 | 1900-01-01 |
ENDDATE | 2079-06-06 | 2079-06-06 | 2079-06-06 |
FORMALNAME | Пермский | Пермская | Коми-Пермяцкий |
OFFNAME | Пермский | Пермская | Коми-Пермяцкий |
SHORTNAME | край | обл | АО |
Значения полей:
- ACTSTATUS для Коми-Пермяцкого АО сохранен в значении "Актуальный";
- OPERSTATUS не изменился - ошибочно(?);
- CURRSTATUS правильный (0 - актуальный, 1 - исторический, 51 - переподчиненный);
- LIVESTATUS показывает единственную актуальную запись, но значения инвертированы (см. прим. 1).
//ToDo - изменения в подчиненных объектах
Примечания:
- Все актуальные записи (CURRSTATUS = 0) имеют значение (LIVESTATUS = 1) и наоборот. Очевидно, что поведение LIVESTATUS не соответствует описанному в документации. Поле можно использовать для выбора актуальных записей, но с осторожностью до выяснения ситуации в будущем.
Исторические названия
Поля AOID, PREVID, NEXTID в совокупности составляют цепочку от современного к устаревшим наименованиям объекта. Хотя, если имеется два прямых предка (как в примере про "Пермский край"), то наследование невозможно отразить полностью однозначно.
В общем виде получение исторических вариантов наименований объекта имеет вид:
WITH RECURSIVE old_names AS (
SELECT *
FROM addrobj
-- вариации отдельной записи:
WHERE aoid = '002ff6b9-c2db-46e5-99da-8cf30d239b27'
-- полный список:
-- WHERE currstatus = 0 AND previd IS NOT NULL
UNION
SELECT addrobj.*
FROM old_names, addrobj
WHERE (addrobj.nextid = old_names.aoid)
)
SELECT * FROM old_names
Примеры:
shortname | formalname | actstatus | operstatus | currstatus | livestatus | updatedate | startdate | enddate |
д | Малое Пермиево | 1 | 21 | 0 | 1 | 2012-09-08 | 2012-02-01 | 2079-06-06 |
д | Малое Пермиево | 0 | 1 | 2 | 0 | 2011-09-14 | 1900-01-01 | 2012-02-01 |
с | Малое Пермиево | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
... | ||||||||
ул | Подстанция 220 | 1 | 20 | 0 | 1 | 2012-03-12 | 1911-11-11 | 2079-06-06 |
ул | Подстанция (Комиссарово) | 0 | 1 | 1 | 0 | 2011-09-15 | 1900-01-01 | 1911-11-11 |
... | ||||||||
пер | Рябиновый | 1 | 20 | 0 | 1 | 2011-09-27 | 1900-01-01 | 2079-06-06 |
ул | Рябиновая | 0 | 1 | 1 | 0 | 2011-09-15 | 1900-01-01 | 2079-06-06 |
... | ||||||||
снт | Восход(п.Селезнево) | 1 | 1 | 0 | 1 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
дп | СТ Восход(п.Селезнево) | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
... | ||||||||
ул | Самбуева В.М. | 1 | 1 | 0 | 1 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
ул | Ф.Энгельса | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
... | ||||||||
проезд | 3-й Лабинский | 1 | 1 | 0 | 1 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
ул | Лабинская 2-я | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
// ToDo:
Примечания:
- Наблюдение (в документации не разъяснено): при внесении изменений, предыдущая историческая запись получает значение (CURRSTATUS = 1). Если вносится повторное изменение, то аннулируемая запись принимает значение (CURRSTATUS = 2). Таким образом, цепочка от современного названия к самому старому принимает вид: актуальное (0), предыдущее (3), более раннее (2), самое старое (1).
Адресные классификаторы
Записи в БД ФИАС содержат ссылки на другие российские адресные классификаторы:
- OKATO - код объекта административно-территориального деления (ОКАТО)
- OKTMO - код муниципального образования (ОКТМО)
- CODE - код КЛАДР
- PLAINCODE - код КЛАДР без признака актуальности (последних двух цифр), см. также CURRSTATUS
ФИАС предлагает собственный "классификационный код", который хранится, разбитым на отдельные элементы: REGIONCODE, AUTOCODE, AREACODE, CITYCODE, CTARCODE, PLACECODE, STREETCODE, EXTRCODE, SEXTCODE.
В целом, код является расширенным вариантом КЛАДР:
СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ ФИАС: 74 0 026 000 000 032 0021 0000 000 КЛАДР: 74 026 000 032 0021
Другой пример:
СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ ФИАС: 33 0 003 001 000 000 0000 0303 000, "Владимирская обл, Вязниковский р-н, г Вязники, снт Коллективный сад Рябинушка-1" КЛАДР: 33 003 001 000 0303
Могут быть случаи, когда адресному объекту в БД ФИАС не соответствует никакой КЛАДР-код, например:
СС А РРР ГГГ ВВВ ППП УУУУ ЭЭЭЭ ЦЦЦ ФИАС: 23 0 000 002 000 000 0000 0383 009, "Краснодарский край, г Армавир, мкр Северный жилой район микрорайон 8, ул Спортивная"
Подробное описание см. в документе "Сведения о составе информации Федеральной информационной адресной системы".
Прочие поля
- Ведомственные классификаторы ФНС России: СОНО - IFNSFL, IFNSUL; СОУН - TERRIFNSFL, TERRIFNSUL.
- CENTSTATUS - статус центра; ненулевое значение присвоено столицам, административным центрам и центральным районам регионов (подробнее см. табл. CENTERST).
- NORMDOC - нормативный документ (табл. NORMDOC).
Обновление БД ФИАС
Привожу текст из документа СВЕДЕНИЯ О СОСТАВЕ ИНФОРМАЦИИ ФЕДЕРАЛЬНОЙ ИНФОРМАЦИОННОЙ АДРЕСНОЙ СИСТЕМЫ.
- На портал ФИАС выгружаются актуальные и исторические сведения ФИАС, а так же технологически удалённые из БД ФИАС адресные сведения.
- Актуальные и исторические сведения ФИАС выгружается в виде файлов (таблиц) DBF и файлов XML.
- Вместе с полной базой ФИАС выгружаются дельта данные – новые, изменившиеся и удаленные данные с момента предыдущей выгрузки базы.
- Дельта данные, т.е. новые, изменившиеся и удаленные данные появившиеся с момента предыдущей выгрузки базы ФИАС, загружаются по следующему алгоритму: по наличию или отсутствию ключа в пользовательской базе определяется тип операции – добавление или обновление записи. После проведения соответствующих операций необходимо удалить по ключу записи, присутствующие в таблицах технологически удаленных данных.
Наличие таких "дельт" позволяет быстро обновить БД ФИАС, не скачивая полный архив (на 2014.12.01 его размер составляет 1.8 Гб). Алгоритм обнобления, действительно, довольно прост. Привожу текст процедуры обновления для MySQL на примере таблицы ADDROBJ:
-- предположим, что дельту "залили" в схему "delta", а обновляемый ФИАС находится в схеме "fias"
use delta;
update
fias.ADDROBJ f
inner join ADDROBJ d on d.AOID = f.AOID
set
f.actstatus=d.actstatus,f.aoguid=d.aoguid,f.aoid=d.aoid,f.aolevel=d.aolevel,f.areacode=d.areacode,f.autocode=d.autocode,f.centstatus=d.centstatus,f.citycode=d.citycode,f.code=d.code,f.currstatus=d.currstatus,f.enddate=d.enddate,f.formalname=d.formalname,f.ifnsfl=d.ifnsfl,f.ifnsul=d.ifnsul,f.nextid=d.nextid,f.offname=d.offname,f.okato=d.okato,f.oktmo=d.oktmo,f.operstatus=d.operstatus,f.parentguid=d.parentguid,f.placecode=d.placecode,f.plaincode=d.plaincode,f.postalcode=d.postalcode,f.previd=d.previd,f.regioncode=d.regioncode,f.shortname=d.shortname,f.startdate=d.startdate,f.streetcode=d.streetcode,f.ctarcode=d.ctarcode,f.extrcode=d.extrcode,f.sextcode=d.sextcode,f.livestatus=d.livestatus,f.normdoc=d.normdoc,f.terrifnsfl=d.terrifnsfl,f.terrifnsul=d.terrifnsul,f.updatedate=d.updatedate;
insert into fias.ADDROBJ (actstatus,aoguid,aoid,aolevel,areacode,autocode,centstatus,citycode,code,currstatus,enddate,formalname,ifnsfl,ifnsul,nextid,offname,okato,oktmo,operstatus,parentguid,placecode,plaincode,postalcode,previd,regioncode,shortname,startdate,streetcode,ctarcode,extrcode,sextcode,livestatus,normdoc,terrifnsfl,terrifnsul,updatedate)
select
d.actstatus,d.aoguid,d.aoid,d.aolevel,d.areacode,d.autocode,d.centstatus,d.citycode,d.code,d.currstatus,d.enddate,d.formalname,d.ifnsfl,d.ifnsul,d.nextid,d.offname,d.okato,d.oktmo,d.operstatus,d.parentguid,d.placecode,d.plaincode,d.postalcode,d.previd,d.regioncode,d.shortname,d.startdate,d.streetcode,d.ctarcode,d.extrcode,d.sextcode,d.livestatus,d.normdoc,d.terrifnsfl,d.terrifnsul,d.updatedate
from
ADDROBJ d
left join fias.ADDROBJ f on d.AOID = f.AOID
where f.AOID is null;
delete from fias.ADDROBJ where aoid in (select aoid from DADDROBJ);
Иногда может изменятся структура самих таблиц, что требует ручного контроля. Например, колонка "oktmo" сначала содержала 8 символов, а потом была расширена до 11 символов.
Тем не менне, несмотря на удобство обновления через дельты, я рекомендую для обновления заменять БД ФИАС целиком (а после этого объединять её с таблицами технологически удалённых данных, при необходимости). Дело в том, что дельты могут содержать неполную информацию, проще говоря oldfias + delta != newfias. Например, я обновлял БД ФИАС от 2012.07.01 через дельты до состояния на 2012.09.24. Если в дельте была информация о переподчинении или об изменении адресного объекта, то предыдущая версия адресного объекта не обновлялась, т.е. не проставлялось (NEXTID = ид_нового, LIVESTATUS = 0, ACTSTATUS = 0). В результате в БД ФИАС были объекты с одинаковым AOGUID, но имеющие ACTSTATUS = 1. Некоторые новые данные просто отсутствовали в дельте. Возможно, что разработчики ФИАС уже исправили эти ошибки, и более свежие дельты следующие за 2012.09.24 содержат полную информацию, но это требует проверки.
Ошибки БД ФИАС
БД ФИАС может содержать ошибки в данных, а) связанные с нарушением целостности двунаправленных списков PREVID/NEXTID, б) ошибки, когда запись об адресном объекте имеет OPERSTATUS = 1, а в действительности произошла другая операция (переименование, переподчинение, слияние, или дробление), и в) ошибки, когда отсутствуют исторические сведения (вызванные тем, что администраторы БД ФИАС, видимо, выполняли прямое изменение данных с помощью SQL-запросов).
Для иллюстрации можно открыть портал ФИАС и воспользоваться расширенным поиском. В поле "Регион" введите "Санкт-Петербург город", в поле "Уровень" выберите "Регион". Нажмите "Найти". Если просмотреть историю изменения города Санкт-Петербург, то можно обнаружить, что Санкт-Петербург раньше назывался "станция Володарская", а должно быть "Ленинград". Это иллюстрирует нарушение целостности двунаправленных списков.
Для иллюстрации ситуации, когда отсутствуют исторические сведения можно рассмотреть адресный объект с AOGUID="df84b14c-6006-46d1-8ce3-3a6ddf8643bd". В БД ФИАС от 2012.08.06 этот объект имел КЛАДР код равный 24000001101000100. В какой-то момент произошло переподчинение родительского объекта, и в итоге у него изменился уровень AOLEVEL с 6 на 90. Соответственно, уровень AOLEVEL дочернего объекта изменился с 7 на 91. Если взять БД ФИАС от 2014.12.01, то в ней нельзя обнаружить исторической записи с КЛАДР кодом равным 24000001101000100. Нет этой записи и в таблицах DADDROBJ.
Ошибки с неправильным OPERSTATUS слишком многочисленны, их классифицирование выходит за рамки данной статьи.