ݺߣ

ݺߣShare a Scribd company logo
Иерархические структуры в реляционных базах данных Adjacency List;
Materialized Path;
Nested Sets;
Так что же использовать?;Иерархические структуры в реляционных базах данных: Adjacency List (Вложенные множества)
Adjacency List (Смежные вершины) Метод хранения Adjacency List;
 Видынаследования;
Использование;
Управление;Иерархические структуры в реляционных базах данных: Adjacency List (Вложенные множества)
Метод хранения Adjacency ListСхема:idpididpididpidpidididpididpididpididpididpidПравила: Каждому pidсоответствует свой id;
На уровне узла pidотличен от id;
Для корневых узлов pid IS NULL;
Узел не должен подчиняться своему потомку.Свойства: Для поддержки структуры дерева требуется 2 поля (id и pid);
Узел напрямую связан с родителем;
С узлом напрямую связаны дети;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
В качестве примеров:Рубрикатор:Комментарии:Сообщение 1комментарий 1.1
ответ на комментарий
…
…
 комментарий 1.2
 ответ на комментарий
…
…Сообщение 2 комментарий 2.1
 ответ на комментарий
 …
 …
 комментарий 2.2
 ответ на комментарий
 …
…… Товары
 Мониторы

More Related Content

What's hot (20)

Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Groovy jug-moscow-part 1
Groovy jug-moscow-part 1
Evgeny Borisov
Работа с БД в Drupal 7
Работа с БД в Drupal 7Работа с БД в Drupal 7
Работа с БД в Drupal 7
Eugene Fidelin
Perl: Symbol table
Perl: Symbol tablePerl: Symbol table
Perl: Symbol table
Elena Shishkina
Jquery selector optimization in drupal
Jquery selector optimization in drupalJquery selector optimization in drupal
Jquery selector optimization in drupal
Yury Glushkov
О безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersО безопасном использовании PHP wrappers
О безопасном использовании PHP wrappers
Positive Hack Days
Контейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООПКонтейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООП
itclub_kz
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
PVasili
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
MageCloud
Разработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIРазработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PI
Ilya Chesnokov
Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16
Anatoly Sharifulin
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в Magento
Magecom Ukraine
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)
Pavel Novitsky
Javascript
JavascriptJavascript
Javascript
Vasya Petrov
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
Vasya Petrov
Entity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай РусланEntity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай Руслан
DrupalSib
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
Яковенко Кирилл
PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
Noveo
Работа с БД в Drupal 7
Работа с БД в Drupal 7Работа с БД в Drupal 7
Работа с БД в Drupal 7
Eugene Fidelin
Jquery selector optimization in drupal
Jquery selector optimization in drupalJquery selector optimization in drupal
Jquery selector optimization in drupal
Yury Glushkov
О безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersО безопасном использовании PHP wrappers
О безопасном использовании PHP wrappers
Positive Hack Days
Контейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООПКонтейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООП
itclub_kz
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
PVasili
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
MageCloud
Разработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIРазработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PI
Ilya Chesnokov
Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16
Anatoly Sharifulin
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в Magento
Magecom Ukraine
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)
Pavel Novitsky
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
Vasya Petrov
Entity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай РусланEntity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай Руслан
DrupalSib
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
Яковенко Кирилл
PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
Noveo

Viewers also liked (8)

Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...
Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...
Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...
Media Gorod
Инфраструктура крупного географически распределенного интернет проекта: техн...
Инфраструктура крупного географически распределенного интернет проекта:  техн...Инфраструктура крупного географически распределенного интернет проекта:  техн...
Инфраструктура крупного географически распределенного интернет проекта: техн...
Media Gorod
Постановка задачи на разработку web-систем: что должен знать исполнитель на с...
Постановка задачи на разработку web-систем: что должен знать исполнитель на с...Постановка задачи на разработку web-систем: что должен знать исполнитель на с...
Постановка задачи на разработку web-систем: что должен знать исполнитель на с...
Media Gorod
От e-commerce к de-commerce
От e-commerce к de-commerceОт e-commerce к de-commerce
От e-commerce к de-commerce
Media Gorod
Semantic Web & электронные сми илья клинцов
Semantic Web & электронные сми   илья клинцовSemantic Web & электронные сми   илья клинцов
Semantic Web & электронные сми илья клинцов
Media Gorod
как организовать работу с юзабилити подрядчиком платон днепровский
как организовать работу с юзабилити подрядчиком   платон днепровскийкак организовать работу с юзабилити подрядчиком   платон днепровский
как организовать работу с юзабилити подрядчиком платон днепровский
Media Gorod
тарифный план битрикс дмитрий росляков
тарифный план битрикс   дмитрий росляковтарифный план битрикс   дмитрий росляков
тарифный план битрикс дмитрий росляков
Media Gorod
Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...
Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...
Кирилл Мавродиев, Intel – Обзор современных возможностей по распараллеливанию...
Media Gorod
Инфраструктура крупного географически распределенного интернет проекта: техн...
Инфраструктура крупного географически распределенного интернет проекта:  техн...Инфраструктура крупного географически распределенного интернет проекта:  техн...
Инфраструктура крупного географически распределенного интернет проекта: техн...
Media Gorod
Постановка задачи на разработку web-систем: что должен знать исполнитель на с...
Постановка задачи на разработку web-систем: что должен знать исполнитель на с...Постановка задачи на разработку web-систем: что должен знать исполнитель на с...
Постановка задачи на разработку web-систем: что должен знать исполнитель на с...
Media Gorod
От e-commerce к de-commerce
От e-commerce к de-commerceОт e-commerce к de-commerce
От e-commerce к de-commerce
Media Gorod
Semantic Web & электронные сми илья клинцов
Semantic Web & электронные сми   илья клинцовSemantic Web & электронные сми   илья клинцов
Semantic Web & электронные сми илья клинцов
Media Gorod
как организовать работу с юзабилити подрядчиком платон днепровский
как организовать работу с юзабилити подрядчиком   платон днепровскийкак организовать работу с юзабилити подрядчиком   платон днепровский
как организовать работу с юзабилити подрядчиком платон днепровский
Media Gorod
тарифный план битрикс дмитрий росляков
тарифный план битрикс   дмитрий росляковтарифный план битрикс   дмитрий росляков
тарифный план битрикс дмитрий росляков
Media Gorod

Similar to Вебинар Томулевича adjacency (20)

Trees in RDBs
Trees in RDBsTrees in RDBs
Trees in RDBs
Aleksey Kutepov
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
ZFConf Conference
Query perfomance tuning
Query perfomance tuningQuery perfomance tuning
Query perfomance tuning
collabock
UWDC 2013, Yii2
UWDC 2013, Yii2UWDC 2013, Yii2
UWDC 2013, Yii2
Alexander Makarov
Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3
Evgeny Gazdovsky
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
Technopark
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2
Paul Klimov
MySQL
MySQLMySQL
MySQL
Noveo
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий ВахрушевАрхитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
it-people
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
Technopark
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2
Ilyas Salikhov
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Symfoniacs
Rubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOPRubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOP
Rubizza
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.
Igor Shkulipa
Spring data jee conf
Spring data jee confSpring data jee conf
Spring data jee conf
Evgeny Borisov
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
ZFConf Conference
Query perfomance tuning
Query perfomance tuningQuery perfomance tuning
Query perfomance tuning
collabock
Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3
Evgeny Gazdovsky
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
Technopark
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2
Paul Klimov
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий ВахрушевАрхитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
it-people
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
Technopark
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2
Ilyas Salikhov
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Symfoniacs
Rubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOPRubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOP
Rubizza
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.
Igor Shkulipa

More from Media Gorod (20)

Iidf market watch_2013
Iidf market watch_2013Iidf market watch_2013
Iidf market watch_2013
Media Gorod
Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013
Media Gorod
13909772985295c7a772abc7.11863824
13909772985295c7a772abc7.1186382413909772985295c7a772abc7.11863824
13909772985295c7a772abc7.11863824
Media Gorod
Ishounkina internet research-projects
Ishounkina internet research-projectsIshounkina internet research-projects
Ishounkina internet research-projects
Media Gorod
Orlova pay u group_290813_
Orlova pay u group_290813_Orlova pay u group_290813_
Orlova pay u group_290813_
Media Gorod
Ep presentation (infographic 2013)
Ep presentation (infographic 2013)Ep presentation (infographic 2013)
Ep presentation (infographic 2013)
Media Gorod
Iway slides e-travel_2013-11_ready
Iway slides e-travel_2013-11_readyIway slides e-travel_2013-11_ready
Iway slides e-travel_2013-11_ready
Media Gorod
Data insight e-travel2013
Data insight e-travel2013Data insight e-travel2013
Data insight e-travel2013
Media Gorod
Электронное Правительство как Продукт
Электронное Правительство как ПродуктЭлектронное Правительство как Продукт
Электронное Правительство как Продукт
Media Gorod
Lean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean StartupLean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean Startup
Media Gorod
Глобальный взгляд на мобильный мир (Nielsen)
 Глобальный взгляд на мобильный мир (Nielsen) Глобальный взгляд на мобильный мир (Nielsen)
Глобальный взгляд на мобильный мир (Nielsen)
Media Gorod
Как россияне используют смартфоны (Nielsen)
 Как россияне используют смартфоны (Nielsen) Как россияне используют смартфоны (Nielsen)
Как россияне используют смартфоны (Nielsen)
Media Gorod
Мобильный интернет в России (MailRuGroup)
Мобильный интернет в России (MailRuGroup) Мобильный интернет в России (MailRuGroup)
Мобильный интернет в России (MailRuGroup)
Media Gorod
Karlovyvaryparti 130406024405-phpapp02
Karlovyvaryparti 130406024405-phpapp02Karlovyvaryparti 130406024405-phpapp02
Karlovyvaryparti 130406024405-phpapp02
Media Gorod
Iidf market watch_2013
Iidf market watch_2013Iidf market watch_2013
Iidf market watch_2013
Media Gorod
Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013
Media Gorod
13909772985295c7a772abc7.11863824
13909772985295c7a772abc7.1186382413909772985295c7a772abc7.11863824
13909772985295c7a772abc7.11863824
Media Gorod
Ishounkina internet research-projects
Ishounkina internet research-projectsIshounkina internet research-projects
Ishounkina internet research-projects
Media Gorod
Orlova pay u group_290813_
Orlova pay u group_290813_Orlova pay u group_290813_
Orlova pay u group_290813_
Media Gorod
Ep presentation (infographic 2013)
Ep presentation (infographic 2013)Ep presentation (infographic 2013)
Ep presentation (infographic 2013)
Media Gorod
Iway slides e-travel_2013-11_ready
Iway slides e-travel_2013-11_readyIway slides e-travel_2013-11_ready
Iway slides e-travel_2013-11_ready
Media Gorod
Data insight e-travel2013
Data insight e-travel2013Data insight e-travel2013
Data insight e-travel2013
Media Gorod
Электронное Правительство как Продукт
Электронное Правительство как ПродуктЭлектронное Правительство как Продукт
Электронное Правительство как Продукт
Media Gorod
Lean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean StartupLean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean Startup
Media Gorod
Глобальный взгляд на мобильный мир (Nielsen)
 Глобальный взгляд на мобильный мир (Nielsen) Глобальный взгляд на мобильный мир (Nielsen)
Глобальный взгляд на мобильный мир (Nielsen)
Media Gorod
Как россияне используют смартфоны (Nielsen)
 Как россияне используют смартфоны (Nielsen) Как россияне используют смартфоны (Nielsen)
Как россияне используют смартфоны (Nielsen)
Media Gorod
Мобильный интернет в России (MailRuGroup)
Мобильный интернет в России (MailRuGroup) Мобильный интернет в России (MailRuGroup)
Мобильный интернет в России (MailRuGroup)
Media Gorod
Karlovyvaryparti 130406024405-phpapp02
Karlovyvaryparti 130406024405-phpapp02Karlovyvaryparti 130406024405-phpapp02
Karlovyvaryparti 130406024405-phpapp02
Media Gorod

Вебинар Томулевича adjacency

  • 1. Иерархические структуры в реляционных базах данных Adjacency List;
  • 4. Так что же использовать?;Иерархические структуры в реляционных базах данных: Adjacency List (Вложенные множества)
  • 5. Adjacency List (Смежные вершины) Метод хранения Adjacency List;
  • 8. Управление;Иерархические структуры в реляционных базах данных: Adjacency List (Вложенные множества)
  • 9. Метод хранения Adjacency ListСхема:idpididpididpidpidididpididpididpididpididpidПравила: Каждому pidсоответствует свой id;
  • 10. На уровне узла pidотличен от id;
  • 12. Узел не должен подчиняться своему потомку.Свойства: Для поддержки структуры дерева требуется 2 поля (id и pid);
  • 13. Узел напрямую связан с родителем;
  • 14. С узлом напрямую связаны дети;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 17.
  • 18.
  • 20. ответ на комментарий
  • 21.
  • 23. ответ на комментарий
  • 27. ответ на комментарий
  • 32. 15”
  • 33. 17”
  • 34.
  • 35. NEC
  • 43.
  • 46.
  • 47. HP
  • 48.
  • 49. …Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 50. Виды наследований1. Одиночное наследование:idpidid INTEGERidpididpidpididpid INTEGER…idpididpididpididpididpid1. Множественное наследование:idpididpididpididpididpidid INTEGER?idpidsidpidspidsidpidsidpidsid?pid INTEGER[]…idpidsidpidsidpidsidpidsidpidsИерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 51. Множественное наследованиеidpididpididpididpididpididpidsidpidspidsidpidsidpidsididpidsidpidsidpidsidpidsidpidsПриведение к одиночному наследованию:idpididpidpididpididpididpididpididpididpididpididpididpididpididpididИерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 52. Множество деревьевtididpididpidtididpididpididpididpidtidtidtidtididpididpididpididpididpididpididpididpidtidtidtidtidtidtidtidtidTree 1Tree 2Trees table (сообщения)Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 53. Структуры таблицМножественное наследование:JOINtreeitemsid INTEGERid INTEGERid INTEGER…pid INTEGERpid INTEGERiid INTEGERtid INTEGERМножество деревьев:WHEREtreetreesid INTEGER…Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 55. ответ на комментарий
  • 57.
  • 58.
  • 60. ответ на комментарий
  • 62.
  • 63.
  • 64.
  • 65.
  • 69. 15”
  • 70. 17”
  • 71.
  • 72. NEC
  • 80.
  • 83.
  • 84. HP
  • 85.
  • 89. Подчиненная ветка;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 90. Использование Adjacency ListЗадачи: Родительский узел;
  • 93. Подчиненная ветка;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 94. Использование Adjacency ListПолучение смежных узлов:Родительский узел:SELECT * FROMmy_treeWHERE id = [pid];Подчиненные узлы:SELECT * FROMmy_treeWHEREpid = [id];Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 95. Использование Adjacency ListПолучение родительской ветви:С использованием JOIN:SELECT * FROMmy_treeAS l4 JOINmy_treeAS l3 ON l3.id = l4.pid JOINmy_treeAS l2 ON l2.id = l3.pid JOINmy_treeAS l1 ON l1.id = l2.pid ... WHERE l4.id = [item.pid];С использованием UNION:SELECT l1.*, 1 AS levelFROMmy_treeAS l1 WHERE l1.id = [item.pid]UNIONSELECT l2.*, 2 AS level FROMmy_treeAS l1 JOINmy_treeAS l2 ON l2.id = l1.pid WHERE l1.id = [item.pid]UNIONSELECT l3.*, 3 AS level FROMmy_treeAS l1 JOINmy_treeAS l2 ON l2.id = l1.pid JOINmy_treeAS l3 ON l3.id = l2.pid WHERE l1.id = [item.pid]...ORDERBY level DESC;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 96. Использование Adjacency ListПолучение родительской ветви:С использованием WITH RECURSIVE (PostgreSQL 8.4):WITH RECURSIVEparentsAS (SELECT *, ARRAY[t.id] AS exist, FALSE AS cycle FROMmy_treeAS t WHERE id = [item.pid]UNION ALL SELECT t.*, exist || t.id, t.id = ANY(exist) FROMparentsAS p, my_treeAS t WHERE t.id = p.pid AND NOT cycle ) SELECT * FROMparents WHERE NOT cycle LIMIT[max_deep];WITH RECURSIVE мы создаем рекурсивный подзапрос parents.Первый запрос рекурсии, в нем указываем точку отсчета. Второй запрос, собственно, рекурсивный запрос. Поле exist - массив уже полученных id, который мы проверяем в поле cycle, что бы не уйти в бесконечную рекурсию. LIMIT ограничивает глубину выборки ветки, так как родитель у узла может быть только лишь один.Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 97. Использование Adjacency ListПолучение родительской ветви (на уровне приложения):Рекурсивная функция:...subparent_recurse {my%params = @_;# Текущая глубина рекурсии$params{deep} ||= 1;# Хеш ранее выбранных узлов$params{exist} ||= {};# Возвращаем пустой список если превысили максимальную заданную глубину рекурсииreturn () if$params{deep} && $params{max_deep} && $params{deep} > $params{max_deep};# делаем запрос к базе данных на поллучение следующего узлаmy$query = 'SELECT * FROM my_tree WHERE id = ' . $params{pid};my$sth = $dbh->prepare($query); $sth->execute;my$item = $sth->fetchrow_hashref;$sth->finish;# Объявляем внутренний список узлов – родителейmy@parents= ();# Если узел найден и у него явно есть родитель, тоif($item&& $item->{pid}) {# Для начала проверим, а не выбирали ли мы уже такой родительский узелreturn () if$params{exist}->{$item->{pid}};# Не выбирали, тогда добавляем в хеш$params{exist}->{$item->{id}} = 1;# И вызываем снова рекурсивную функцию@parents = &parent_recurse(pid => $item->{pid},max_deep => $params{max_deep},deep => $params{deep} + 1,exist => $params{exist} ); }# Добавлем выбранный узел к массиву, если естьpush@parents, $itemif$item;# Возвращаем список выбранных узловreturn@parents;}...my@parents = &parent_recurse(pid => $item->{pid}, max_deep => 2);...Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 98. Использование Adjacency ListПолучение родительской ветви (на уровне приложения):Динамический массив:...# Объявляем пустой список родителейmy@parents= ();# Объявляем хеш уже полученных узлов, и добавляем в него id текущего узлаmy%exist= ($item->{id} => 1);# Объявляем динамический массив и вносим в него текущий узелmy@while = ($item);# Максимальная глубина выборкиmy$max_deep = 3;# Текущая глубина выборкиmy$deep = 1;# В цикле отрезаем первый эмемент динамического массива до тех пор пока это возможноwhile (my$item = shift @while && $deep <= $max_deep) {# Прерываем цикл, если узла явно нет родителя или такого родителя мы уже получалиlastif!$item->{pid} || $exist{$item->{pid}};# Делаем запрос к базе данныхmy$query = 'SELECT * FROM my_tree WHERE id = ' . $item->{pid};my$sth = $dbh->prepare($query); $sth->execute;my$parent = $sth->fetchrow_hashref;$sth->finish;# Прерываем цикл, если узел не получилиlastunless$parent;# Добавляем узел в массив родителейpush@parents, $parent;# Добавляем id узла в хеш полученных узлов$exist{$parent->{id}} = 1;# Добавляем узел в динамический массивpush@while, $parent;# Инкрементим текущую глубину$deep++;}...Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 99. Использование Adjacency ListПолучение родительской ветви:Хранимая процедура PostgreSQL:CREATE OR REPLACE FUNCTION "public"."get_parents" (pid_in INTEGER,deep INTEGER) RETURNS SETOF "public"."my_tree" AS$body$DECLAREexist_ids INTEGER[] := ARRAY[0]; -- Для пустого массива плохо работает ALLpid_now INTEGER := pid_in; -- Текущий piddeep_now INTEGER := deep; -- Текущаа глубинаitemmy_tree;BEGINWHILEpid_nowIS NOT NULL AND pid_now > 0 ANDpid_now <> ALL (exist_ids) AND(deep_nowIS NULL OR deep_now > 0)LOOPSELECT * INTOitemFROMmy_treeWHEREid = pid_now;IFitem.idIS NULL THENEXIT;END IF;RETURN NEXT item;pid_now := item.pid;exist_ids := exist_ids || item.id;IFdeep_nowIS NOT NULL THEN deep_now := deep_now – 1;END IF;END LOOP;RETURN;END;$body$LANGUAGE 'plpgsql';-- Для красоты добавим функцию с одним передаваемым параметромCREATE OR REPLACE FUNCTION "public"."get_parents" (pid_in INTEGER) RETURNSSETOF "public"."my_tree" AS$body$SELECT * FROMget_parents( $1, NULL );$body$LANGUAGE'sql';Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 100. Использование Adjacency ListПолучение родительской ветви:Хранимая процедура MySQL:CREATE DEFINER = CURRENT_USER PROCEDURE `get_parents`( IN pid_in INTEGER, IN max_deep INTEGER )BEGINDECLAREid_now INTEGER;DECLAREpid_now INTEGER DEFAULT pid_in;DECLARE field1_now TEXT;DECLAREexist TEXT DEFAULT '|';WHILEpid_now > 0 ANDexistNOT LIKE CONCAT('%|', pid_now, '|%') AND (max_deepIS NULL OR max_deep > 0)DOSELECT * INTOid_now, pid_now, field1_nowFROMmy_treeWHEREid = pid_now;SELECTid_now, pid_now, field1_now;IF (max_deepIS NOT NULL)THENSETmax_deep = max_deep - 1;END IF;SETexist = CONCAT(exist, id_now, '|'); END WHILE;END;Примечание: Возвращается несколько result set.Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 101. Использование Adjacency ListПолучение дочерней ветви:С использованием WITH RECURSIVE (PostgreSQL 8.4):WITH RECURSIVE childrenAS (SELECT *,pid || '|' || [order_field]ASord, ARRAY[id] ASexist, FALSE AScycleFROMmy_treeWHEREpid = [item.id]UNION ALLSELECTt.*,ord || '.' || t.pid || '|' || t.[order_field],exist || t.id,t.id = ANY(exist)FROMchildren AS c,my_tree AS tWHEREt.pid = c.idANDNOTcycleANDarray_length(exist, 1) < [max_deep]) SELECT * FROMchildrenWHERE NOT cycleORDER BY ordLIMIT[limit];Где: [order_field] - поле сортировки в пределах подчинения;
  • 102. [item.id] - ID узла от которого производится выборка;
  • 103. [max_deep] - максимальная глубина рекурсии;
  • 104. [limit] - количество выбираемых строк;Основной особенностью этого запроса является дополнительное поле path, которое практически является Materializedpath, за исключением того, что мы добавляем в него дополнительное поле сортировки текущего узла.Причем защита от зацикливания (поля exist и cycle) локализована в пределах отдельных ветвей, поэтому это хоть и предохранит от бесконечного зацикливания, но позволит повторно выбрать строки, так что будте внимательны.Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 105. Использование Adjacency ListПолучение дочерней ветви (на уровне приложения):Рекурсивная функция:...subchild_recurse {my%params= @_;# Текущая глубина рекурсии$params{deep} ||= 1;# Хеш ранее выбранных узлов$params{exist} ||= {};# Возвращаем пустой список если превысили максимальную заданную глубину рекурсииreturn () if$params{deep} && $params{max_deep} && $params{deep} > $params{max_deep};# Объявляем внутренний список узлов – потомковmy@children = ();# делаем запрос к базе данных на получение списка подчиненных узловmy$query = 'SELECT * FROM my_tree WHERE pid = ' . $params{pid} . ($params{order} ? ' ORDER BY ' . $params{order} : '');my$sth = $dbh->prepare($query); $sth->execute;while (my$item = $sth->fetchrow_hashref) {# Для начала проверим, а не выбирали ли мы уже такой узелnext () if$params{exist}->{$item->{id}};# Не выбирали, тогда добавляем в хеш$params{exist}->{$item->{id}} = 1;# Добавлем выбранный узел к массивуpush@children, $item;# Вызываем снова рекурсивную функцию для получения подчиненных узлов текущего узлаmy@children_deep = &child_recurse(pid => $item->{id}, max_deep => $params{max_deep}, order => $params{order},deep => $params{deep} + 1, exist => $params{exist},);# Добавляем список подчиненных узлов текущего узлаpush@children, @children_deep; }$sth->finish;# Возвращаем список выбранных узлов return@children;}my@children = &child_recurse(pid => $item->{id}, max_deep => 5, order => 'id');...Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 106. Использование Adjacency ListПолучение дочерней ветви (на уровне приложения):Оптимизация выборки:Ввести денормализацию таблицы создав дополнительное поле счетчика потомков. В этом случае можно будет проверять наличие потомков и делать или нет запрос на их получение. Это решение рассмотрено более детально ниже;Производить выборки не построчно, а списочно, для каждого уровня вложенности. Это решение подробно рассмотрим здесь;SELECTchildren.*FROMmy_treeASchildrenJOINmy_treeASparentsONparents.id = children.pidWHEREchildren.pid = ANY([parents_array])ORDER BYparents.[order_field], children.[order_field];Где:[parents_array] - массив id родительских узлов;[order_field] - поле сортировки;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 107. Использование Adjacency ListПолучение дочерней ветви (на уровне приложения):Динамический массив:...my$max_deep= 5;my$order= 'field1‘;my$limit= 20; my@children= (); my@while= ($item); my%exist= (); my%indexes= (); my$skew= 0; my$pids= []; my$deep_now= 1; while (my$child= shift@while) {nextif$exist{$child->{id}};$exist{$child->{id}} = 1;push@$pids, $child->{id};unless (defined$indexes{$child->{pid} || 'NULL'}) {if ($childne$item) {push@children, $child;$indexes{$child->{id}} = $#children; } } else {splice@children, $indexes{$child->{pid}} + $skew+ 1, 0 , ($child); $indexes{$child->{id}} = $indexes{$child->{pid}} + $skew+ 1;$skew++; }unless ($while[0]) {$skew= 0;$deep_now++;lastif$max_deep&& $deep_now> $max_deep;my$query= 'SELECT children.* FROM my_tree AS childrenJOIN my_tree AS parents ON parents.id = children.pidWHERE children.pid = ANY(?) ORDER BY parents.’.$order.', children.’.$order.($limit ? ' LIMIT ‘.$limit : '');my$sth= $dbh->prepare($query); $sth->execute($pids);while (my$child= $sth->fetchrow_hashref) {push@while, $child}$sth->finish; }}...Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 108. Управление Adjacency ListОсновные действия: Изменение pidузла;Дополнительные действия: Контроль правил;
  • 109. Денормализация (счетчики и уровень).Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 110. Управление Adjacency ListКонтроль подчиненности:Триггер PostgreSQL 8.4 и выше:CREATE OR REPLACE FUNCTION "public"."my_tree_update_trigger" ()RETURNStriggerAS$body$DECLAREtmp_id INTEGER;BEGIN-- Если произошло изменение родителя узлаIFNEW.pidIS NOT NULL AND (NEW.pid <> OLD.pidOROLD.pidIS NULL) THEN-- Пытаемся найти в родителькой ветки нового родителя текущий узелWITH RECURSIVE parentsAS (SELECTt.id, t.pid, ARRAY[t.id] AS exist, FALSE AS cycleFROMmy_treeAStWHEREid = NEW.pidUNION ALL SELECT t.id, t.pid, exist || t.id, t.id = ANY(exist)FROMparentsASp, my_treeAStWHEREt.id = p.pidAND NOT p.cycle )SELECTidINTOtmp_idFROMparentsWHEREid = NEW.idAND NOT cycleLIMIT 1;-- Узел найден, следовательно родителя назначить не можемIFtmp_idIS NOT NULL THENRAISE NOTICE 'Нельзя ставить потомком родителя!';NEW.pid := OLD.pid;END IF;END IF;RETURN NEW;END;$body$LANGUAGE 'plpgsql';CREATE TRIGGER "my_tree_update" BEFORE UPDATEON "public"."my_tree" FOR EACH ROWEXECUTE PROCEDURE "public"."my_tree_update_trigger"();Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 111. Управление Adjacency ListКонтроль подчиненности:Триггер PostgreSQL ниже 8.4:CREATE OR REPLACE FUNCTION "public"."my_tree_update_trigger" ()RETURNStriggerAS$body$DECLAREtmp_id INTEGER;BEGIN-- Если произошло изменение родителя узлаIFNEW.pidIS NOT NULL AND (NEW.pid <> OLD.pid OR OLD.pidIS NULL) THEN-- Пытаемся найти в родителькой ветки нового родителя текущий узелSELECT idINTOtmp_idFROMget_parents(NEW.pid) WHEREid = NEW.id LIMIT 1;-- Узел найден, следовательно родителя назначить не можемIFtmp_idIS NOT NULL THENRAISE NOTICE 'Нельзя ставить потомком родителя!';NEW.pid := OLD.pid;END IF;END IF;RETURN NEW;END;$body$LANGUAGE 'plpgsql';CREATE TRIGGER "my_tree_update" BEFORE UPDATEON "public"."my_tree" FOR EACH ROWEXECUTE PROCEDURE "public"."my_tree_update_trigger"();Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 112. Управление Adjacency ListДенормализацияcounter и level:Триггер на INSERT (PostgreSQL):CREATE OR REPLACE FUNCTION "public"."my_tree_insert_trigger" ()RETURNStrigger AS$body$DECLAREparentmy_tree;BEGIN-- Что денормализовано, то ставить вручную нельзяNEW.counter := 0;NEW.level := 0;-- Если определен pid тогда обновляем счетчик родителяIFNEW.pidIS NOT NULL ORNEW.pid > 0 THEN-- Сразу вернем результат обновления родителя-- Финт ушами с CASE при обновлении счетчика из-за того что NULL + 1 = NULL, -- поэтому эти поля лучше сразу делать NOT NULL, а сейчас перестрахуемсяUPDATEmy_treeSETcounter = CASE WHEN counterIS NULL THEN 1 ELSEcounter + 1 ENDWHEREid = NEW.pidRETURNING * INTOparent;-- Проверим существование родителя, без отмены операцииIFparent.idIS NULL THENRAISE NOTICE 'ОШИБКА! Родителя с таким ID нет (%)', NEW;NEW.pid := 0;ELSE-- Устанавливаем значение level для вставляемого узлаNEW.level := CASE WHEN parent.levelIS NULL OR parent.level = 0 THEN 1 ELSENEW.level + 1 END;END IF;END IF;RETURN NEW;END;$body$LANGUAGE 'plpgsql';CREATE TRIGGER "my_tree_insert" BEFORE INSERT ON "public"."my_tree" FOR EACH ROW EXECUTE PROCEDURE "public"."my_tree_insert_trigger"();Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 113. Управление Adjacency ListДенормализацияcounter и level:Триггер на UPDATE (PostgreSQL):CREATE OR REPLACE FUNCTION "public"."my_tree_update" ()RETURNStrigger AS$body$DECLAREparentmy_tree;childmy_tree;level_skew INTEGER;pids INTEGER[];tmp_pids INTEGER[];exist_update INTEGER[];BEGIN-- Опять же для предотвращения сравнения с NULL ставим 0IFOLD.pidIS NULL THEN OLD.pid := 0; END IF;IFNEW.pidIS NULL THEN NEW.pid := 0; END IF;IFOLD.levelIS NULL THEN OLD.level := 0; END IF;-- Если произошла смена родителяIFNEW.pid <> OLD.pidTHEN-- Уменьшаем счетчик старого родителя если он естьIFOLD.pid > 0 THEN UPDATE my_treeSETcounter = counter - 1 WHEREid = OLD.pid; END IF;-- Увеличиваем счетчик нового родителя если он естьIFNEW.pid > 0 THEN UPDATEmy_treeSETcounter = COALESCE(counter, 0) + 1 WHEREid = NEW.pidRETURNING * INTOparent;-- Проверяем существование родителяIFparent.idIS NULL THENRAISE NOTICE 'ОШИБКА! Родителя с таким ID нет (%)', NEW;NEW.level := 0;NEW.pid := 0;ELSE-- Если родитель есть то устанавливаем новый уровень узлаNEW.level := COALESCE(parent.level, 0) + 1;END IF;ELSENEW.level := 0;END IF;-- Данные по перемещаемому узлу обновили, теперь следует обновить-- level потомков перемещаемого узлаlevel_skew := NEW.level - OLD.level;...Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 114. Управление Adjacency ListДенормализацияcounter и level:Триггер на UPDATE (PostgreSQL), продолжение:...-- Смещение уровня таки естьIFlevel_skew <> 0 THENpids := ARRAY[NEW.id];exist_update := ARRAY[NEW.id]; -- Пока есть узлы у которых есть потомки:WHILEpids[1] IS NOT NULL LOOPtmp_pids := ARRAY[NULL];-- Обновляем всех потомков на уровнеFORchildIN UPDATE my_treeSETlevel = level + level_skewWHEREpid = ANY (pids) ANDid <> ALL (exist_update) RETURNING *LOOP-- Поставим защиту для того, что бы невозможно было поставить узел в починение своему потомкуIFchild.id = NEW.pidTHENRAISE EXCEPTION 'Ошибка! Нельзя ставить узел в подчинение потомку! (%)', NEW;RETURN NULL;END IF;-- Если у потомка еще есть потомки, то добавляем его id в список на обновление-- следующего уровняIFchild.counterIS NOT NULL ANDchild.counter > 0 THENtmp_pids := array_prepend(child.id, tmp_pids);END IF;-- Защита от повторовexist_update := array_append(exist_update, child.id);END LOOP;pids := tmp_pids;END LOOP;END IF;END IF;RETURN NEW;END;$body$LANGUAGE 'plpgsql';CREATE TRIGGER "my_tree_update" BEFORE UPDATEON "public"."my_tree" FOR EACH ROWEXECUTE PROCEDURE "public"."my_tree_update"();Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 115. Управление Adjacency ListДенормализацияcounter и level:Триггер на DELETE (PostgreSQL) :CREATE OR REPLACE FUNCTION "public"."my_tree_delete_trigger" ()RETURNStriggerAS$body$BEGIN-- Если есть родитель, то обновляем его счетчикIFOLD.pidIS NOT NULL AND OLD.pid > 0 THENUPDATEmy_treeSETcounter = counter – 1WHEREid = OLD.pid;END IF;IFcurrent_setting('user_vars.tree_delete') = 'levelup' THENUPDATEmy_treeSETpid = OLD.pid WHERE pid = OLD.id;ELSIFcurrent_setting('user_vars.tree_delete') = 'root' THENUPDATEmy_treeSETpid = 0WHEREpid = OLD.id;ELSEIFOLD.counterIS NOT NULL AND OLD.counter > 0 THENDELETE FROM my_treeWHEREpid = OLD.id;END IF;END IF;RETURN OLD;END;$body$LANGUAGE 'plpgsql';CREATE TRIGGER "my_tree_delete" AFTER DELETEON "public"."my_tree" FOR EACH ROWEXECUTE PROCEDURE "public"."my_tree_delete_trigger"();Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 116. Управление Adjacency ListДенормализацияcounter и level:Способы удаления ветвей:1. Транзакционный:BEGIN;SELECTset_config('user_vars.tree_delete', 'levelup', TRUE);DELETE FROM my_treeWHEREid = [item.id];COMMIT;1. Не транзакционный:DELETE FROM my_treeUSING (SELECTset_config('user_vars.tree_delete', 'root', TRUE) ) ASconfWHEREid = [item.id];Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 117. Вопросы?Статьи по теме: http://doc.prototypes.ru/database/trees/Сергей ТомулевичRambler, Москва, 2010Карикатуры: Сергей КорсунИерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)