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

More Related Content

What's hot

Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Evgeny Borisov
 
Работа с БД в Drupal 7
Работа с БД в Drupal 7Работа с БД в Drupal 7
Работа с БД в Drupal 7Eugene Fidelin
 
PHP Tricks
PHP TricksPHP Tricks
PHP TricksBlackFan
 
Jquery selector optimization in drupal
Jquery selector optimization in drupalJquery selector optimization in drupal
Jquery selector optimization in drupalYury Glushkov
 
О безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersО безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersPositive Hack Days
 
Контейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООПКонтейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООПitclub_kz
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс СерверPVasili
 
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...MageCloud
 
Разработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIРазработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIIlya Chesnokov
 
Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16Anatoly Sharifulin
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в MagentoMagecom 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 в 1Vasya Petrov
 
Entity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай РусланEntity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай РусланDrupalSib
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Яковенко Кирилл
 
PHP Advanced
PHP AdvancedPHP Advanced
PHP AdvancedNoveo
 

What's hot (20)

Groovy jug-moscow-part 1
Groovy jug-moscow-part 1Groovy jug-moscow-part 1
Groovy jug-moscow-part 1
 
Работа с БД в Drupal 7
Работа с БД в Drupal 7Работа с БД в Drupal 7
Работа с БД в Drupal 7
 
Perl: Symbol table
Perl: Symbol tablePerl: Symbol table
Perl: Symbol table
 
PHP Tricks
PHP TricksPHP Tricks
PHP Tricks
 
Jquery selector optimization in drupal
Jquery selector optimization in drupalJquery selector optimization in drupal
Jquery selector optimization in drupal
 
I Net
I NetI Net
I Net
 
О безопасном использовании PHP wrappers
О безопасном использовании PHP wrappersО безопасном использовании PHP wrappers
О безопасном использовании PHP wrappers
 
Контейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООПКонтейнеры и хранение объектов в ООП
Контейнеры и хранение объектов в ООП
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
 
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
Профилирование и оптимизация фреймворков высоконагруженных систем на примере ...
 
Разработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PIРазработка на Perl под Raspberry PI
Разработка на Perl под Raspberry PI
 
Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16
 
Индексирование в Magento
Индексирование в MagentoИндексирование в Magento
Индексирование в Magento
 
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)
 
Javascript
JavascriptJavascript
Javascript
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
Entity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай РусланEntity возрождение легенды. Исай Руслан
Entity возрождение легенды. Исай Руслан
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
 
DBIx Class
DBIx ClassDBIx Class
DBIx Class
 

Viewers also liked

Кирилл Мавродиев, 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-commerceMedia Gorod
 
Semantic Web & электронные сми илья клинцов
Semantic Web & электронные сми   илья клинцовSemantic Web & электронные сми   илья клинцов
Semantic Web & электронные сми илья клинцовMedia Gorod
 
как организовать работу с юзабилити подрядчиком платон днепровский
как организовать работу с юзабилити подрядчиком   платон днепровскийкак организовать работу с юзабилити подрядчиком   платон днепровский
как организовать работу с юзабилити подрядчиком платон днепровскийMedia Gorod
 
тарифный план битрикс дмитрий росляков
тарифный план битрикс   дмитрий росляковтарифный план битрикс   дмитрий росляков
тарифный план битрикс дмитрий росляковMedia Gorod
 

Viewers also liked (8)

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

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

ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf Conference
 
Query perfomance tuning
Query perfomance tuningQuery perfomance tuning
Query perfomance tuningcollabock
 
Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3Evgeny Gazdovsky
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6Technopark
 
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Paul Klimov
 
MySQL
MySQLMySQL
MySQLNoveo
 
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий ВахрушевАрхитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушевit-people
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8Technopark
 
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Symfoniacs
 
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Ilyas Salikhov
 
Rubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOPRubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOPRubizza
 
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.Igor Shkulipa
 

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

Trees in RDBs
Trees in RDBsTrees in RDBs
Trees in RDBs
 
DBIx::Class
DBIx::ClassDBIx::Class
DBIx::Class
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
 
PGDBObject
PGDBObjectPGDBObject
PGDBObject
 
Bytecode
BytecodeBytecode
Bytecode
 
Query perfomance tuning
Query perfomance tuningQuery perfomance tuning
Query perfomance tuning
 
UWDC 2013, Yii2
UWDC 2013, Yii2UWDC 2013, Yii2
UWDC 2013, Yii2
 
Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3Презентация Neo4j на ADD-3
Презентация Neo4j на ADD-3
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2
 
MySQL
MySQLMySQL
MySQL
 
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий ВахрушевАрхитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
Архитектура RESTful API на Pyramid — приемы проектирования Дмитрий Вахрушев
 
Java осень 2014 занятие 8
Java осень 2014 занятие 8Java осень 2014 занятие 8
Java осень 2014 занятие 8
 
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
Расширенное кеширование Doctrine2 (Ильяс Салихов, Intaro)
 
Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2Расширенное кеширование в Doctrine2
Расширенное кеширование в Doctrine2
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 
Jquery
JqueryJquery
Jquery
 
Rubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOPRubizza #1 Lecture Ruby OOP
Rubizza #1 Lecture Ruby OOP
 
C# Web. Занятие 04.
C# Web. Занятие 04.C# Web. Занятие 04.
C# Web. Занятие 04.
 
Spring data jee conf
Spring data jee confSpring data jee conf
Spring data jee conf
 

More from Media Gorod

Iidf market watch_2013
Iidf market watch_2013Iidf market watch_2013
Iidf market watch_2013Media Gorod
 
E travel 2013 ufs-f
E travel 2013 ufs-fE travel 2013 ufs-f
E travel 2013 ufs-fMedia Gorod
 
Travel shop 2013
Travel shop 2013Travel shop 2013
Travel shop 2013Media Gorod
 
Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013Media Gorod
 
13909772985295c7a772abc7.11863824
13909772985295c7a772abc7.1186382413909772985295c7a772abc7.11863824
13909772985295c7a772abc7.11863824Media Gorod
 
As e-travel 2013
As   e-travel 2013As   e-travel 2013
As e-travel 2013Media Gorod
 
Ishounkina internet research-projects
Ishounkina internet research-projectsIshounkina internet research-projects
Ishounkina internet research-projectsMedia 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_readyMedia Gorod
 
Data insight e-travel2013
Data insight e-travel2013Data insight e-travel2013
Data insight e-travel2013Media Gorod
 
Электронное Правительство как Продукт
Электронное Правительство как ПродуктЭлектронное Правительство как Продукт
Электронное Правительство как ПродуктMedia Gorod
 
Lean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean StartupLean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean StartupMedia 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-phpapp02Media Gorod
 

More from Media Gorod (20)

Itogi2013
Itogi2013Itogi2013
Itogi2013
 
Moneytree rus 1
Moneytree rus 1Moneytree rus 1
Moneytree rus 1
 
Iidf market watch_2013
Iidf market watch_2013Iidf market watch_2013
Iidf market watch_2013
 
E travel 2013 ufs-f
E travel 2013 ufs-fE travel 2013 ufs-f
E travel 2013 ufs-f
 
Travel shop 2013
Travel shop 2013Travel shop 2013
Travel shop 2013
 
Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013Kozyakov pay u_e-travel2013
Kozyakov pay u_e-travel2013
 
13909772985295c7a772abc7.11863824
13909772985295c7a772abc7.1186382413909772985295c7a772abc7.11863824
13909772985295c7a772abc7.11863824
 
As e-travel 2013
As   e-travel 2013As   e-travel 2013
As e-travel 2013
 
Ishounkina internet research-projects
Ishounkina internet research-projectsIshounkina internet research-projects
Ishounkina internet research-projects
 
Orlova pay u group_290813_
Orlova pay u group_290813_Orlova pay u group_290813_
Orlova pay u group_290813_
 
Ep presentation (infographic 2013)
Ep presentation (infographic 2013)Ep presentation (infographic 2013)
Ep presentation (infographic 2013)
 
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
 
Data insight e-travel2013
Data insight e-travel2013Data insight e-travel2013
Data insight e-travel2013
 
Электронное Правительство как Продукт
Электронное Правительство как ПродуктЭлектронное Правительство как Продукт
Электронное Правительство как Продукт
 
Lean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean StartupLean мышление / Специфика Lean Startup
Lean мышление / Специфика Lean Startup
 
Глобальный взгляд на мобильный мир (Nielsen)
 Глобальный взгляд на мобильный мир (Nielsen) Глобальный взгляд на мобильный мир (Nielsen)
Глобальный взгляд на мобильный мир (Nielsen)
 
Как россияне используют смартфоны (Nielsen)
 Как россияне используют смартфоны (Nielsen) Как россияне используют смартфоны (Nielsen)
Как россияне используют смартфоны (Nielsen)
 
Мобильный интернет в России (MailRuGroup)
Мобильный интернет в России (MailRuGroup) Мобильный интернет в России (MailRuGroup)
Мобильный интернет в России (MailRuGroup)
 
Meta Mass Media
Meta Mass MediaMeta Mass Media
Meta Mass Media
 
Karlovyvaryparti 130406024405-phpapp02
Karlovyvaryparti 130406024405-phpapp02Karlovyvaryparti 130406024405-phpapp02
Karlovyvaryparti 130406024405-phpapp02
 

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

  • 1.
  • 4. Так что же использовать?;Иерархические структуры в реляционных базах данных: Adjacency List (Вложенные множества)
  • 5.
  • 8. Управление;Иерархические структуры в реляционных базах данных: Adjacency List (Вложенные множества)
  • 9.
  • 10. На уровне узла pidотличен от id;
  • 12.
  • 13. Узел напрямую связан с родителем;
  • 14. С узлом напрямую связаны дети;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 15.
  • 17.
  • 18.
  • 20. ответ на комментарий
  • 21.
  • 22.
  • 23. ответ на комментарий
  • 27. ответ на комментарий
  • 29.
  • 32. 15”
  • 33. 17”
  • 34.
  • 35. NEC
  • 43.
  • 46.
  • 47. HP
  • 48.
  • 49. …Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 50. Виды наследований 1. Одиночное наследование: id pid id INTEGER id pid id pid pid id pid INTEGER … id pid id pid id pid id pid id pid 1. Множественное наследование: id pid id pid id pid id pid id pid id INTEGER ? id pids id pids pids id pids id pids id ? pid INTEGER[] … id pids id pids id pids id pids id pids Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 51. Множественное наследование id pid id pid id pid id pid id pid id pids id pids pids id pids id pids id id pids id pids id pids id pids id pids Приведение к одиночному наследованию: id pid id pid pid id pid id pid id pid id pid id pid id pid id pid id pid id pid id pid id pid id Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 52. Множество деревьев tid id pid id pid tid id pid id pid id pid id pid tid tid tid tid id pid id pid id pid id pid id pid id pid id pid id pid tid tid tid tid tid tid tid tid Tree 1 Tree 2 Trees table (сообщения) Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 53. Структуры таблиц Множественное наследование: JOIN tree items id INTEGER id INTEGER id INTEGER … pid INTEGER pid INTEGER iid INTEGER tid INTEGER Множество деревьев: WHERE tree trees id INTEGER … Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 54.
  • 55. ответ на комментарий
  • 57.
  • 58.
  • 60. ответ на комментарий
  • 62.
  • 63.
  • 64.
  • 65.
  • 69. 15”
  • 70. 17”
  • 71.
  • 72. NEC
  • 80.
  • 83.
  • 84. HP
  • 85.
  • 86.
  • 89. Подчиненная ветка;Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины) Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 90.
  • 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 level FROMmy_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$ DECLARE exist_ids INTEGER[] := ARRAY[0]; -- Для пустого массива плохо работает ALL pid_now INTEGER := pid_in; -- Текущий pid deep_now INTEGER := deep; -- Текущаа глубина itemmy_tree; BEGIN WHILE pid_nowIS NOT NULL AND pid_now > 0 AND pid_now <> ALL (exist_ids) AND(deep_nowIS NULL OR deep_now > 0) LOOP SELECT * 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 ) BEGIN DECLAREid_now INTEGER; DECLAREpid_now INTEGER DEFAULT pid_in; DECLARE field1_now TEXT; DECLAREexist TEXT DEFAULT '|'; WHILEpid_now > 0 AND existNOT LIKE CONCAT('%|', pid_now, '|%') AND (max_deepIS NULL OR max_deep > 0) DO SELECT * INTOid_now, pid_now, field1_now FROMmy_tree WHEREid = pid_now; SELECTid_now, pid_now, field1_now; IF (max_deepIS NOT NULL)THEN SETmax_deep = max_deep - 1; END IF; SETexist = CONCAT(exist, id_now, '|'); END WHILE; END; Примечание: Возвращается несколько result set. Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 101.
  • 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_treeASchildren JOINmy_treeASparentsONparents.id = children.pid WHEREchildren.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 children JOIN my_tree AS parents ON parents.id = children.pid WHERE 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.
  • 109. Денормализация (счетчики и уровень).Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 110. Управление Adjacency List Контроль подчиненности: Триггер PostgreSQL 8.4 и выше: CREATE OR REPLACE FUNCTION "public"."my_tree_update_trigger" () RETURNStriggerAS $body$ DECLARE tmp_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 cycle FROMmy_treeASt WHEREid = NEW.pid UNION ALL SELECT t.id, t.pid, exist || t.id, t.id = ANY(exist) FROMparentsASp, my_treeASt WHEREt.id = p.pidAND NOT p.cycle ) SELECTidINTOtmp_idFROMparentsWHEREid = NEW.idAND NOT cycleLIMIT 1; -- Узел найден, следовательно родителя назначить не можем IFtmp_idIS NOT NULL THEN RAISE NOTICE 'Нельзя ставить потомком родителя!'; NEW.pid := OLD.pid; END IF; END IF; RETURN NEW; END; $body$ LANGUAGE 'plpgsql'; CREATE TRIGGER "my_tree_update" BEFORE UPDATE ON "public"."my_tree" FOR EACH ROW EXECUTE 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$ DECLARE tmp_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 THEN RAISE NOTICE 'Нельзя ставить потомком родителя!'; NEW.pid := OLD.pid; END IF; END IF; RETURN NEW; END; $body$ LANGUAGE 'plpgsql'; CREATE TRIGGER "my_tree_update" BEFORE UPDATE ON "public"."my_tree" FOR EACH ROW EXECUTE 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$ DECLARE parentmy_tree; BEGIN -- Что денормализовано, то ставить вручную нельзя NEW.counter := 0; NEW.level := 0; -- Если определен pid тогда обновляем счетчик родителя IFNEW.pidIS NOT NULL ORNEW.pid > 0 THEN -- Сразу вернем результат обновления родителя -- Финт ушами с CASE при обновлении счетчика из-за того что NULL + 1 = NULL, -- поэтому эти поля лучше сразу делать NOT NULL, а сейчас перестрахуемся UPDATEmy_tree SETcounter = CASE WHEN counterIS NULL THEN 1 ELSEcounter + 1 END WHEREid = NEW.pid RETURNING * INTOparent; -- Проверим существование родителя, без отмены операции IFparent.idIS NULL THEN RAISE 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$ DECLARE parentmy_tree; childmy_tree; level_skew INTEGER; pids INTEGER[]; tmp_pids INTEGER[]; exist_update INTEGER[]; BEGIN -- Опять же для предотвращения сравнения с NULL ставим 0 IFOLD.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 THEN RAISE NOTICE 'ОШИБКА! Родителя с таким ID нет (%)', NEW; NEW.level := 0; NEW.pid := 0; ELSE -- Если родитель есть то устанавливаем новый уровень узла NEW.level := COALESCE(parent.level, 0) + 1; END IF; ELSE NEW.level := 0; END IF; -- Данные по перемещаемому узлу обновили, теперь следует обновить -- level потомков перемещаемого узла level_skew := NEW.level - OLD.level; ... Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 114. Управление Adjacency List Денормализацияcounter и level: Триггер на UPDATE (PostgreSQL), продолжение: ... -- Смещение уровня таки есть IFlevel_skew <> 0 THEN pids := ARRAY[NEW.id]; exist_update := ARRAY[NEW.id]; -- Пока есть узлы у которых есть потомки: WHILEpids[1] IS NOT NULL LOOP tmp_pids := ARRAY[NULL]; -- Обновляем всех потомков на уровне FORchildIN UPDATE my_tree SETlevel = level + level_skew WHEREpid = ANY (pids) ANDid <> ALL (exist_update) RETURNING * LOOP -- Поставим защиту для того, что бы невозможно было поставить узел в починение своему потомку IFchild.id = NEW.pidTHEN RAISE EXCEPTION 'Ошибка! Нельзя ставить узел в подчинение потомку! (%)', NEW; RETURN NULL; END IF; -- Если у потомка еще есть потомки, то добавляем его id в список на обновление -- следующего уровня IFchild.counterIS NOT NULL ANDchild.counter > 0 THEN tmp_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 UPDATE ON "public"."my_tree" FOR EACH ROW EXECUTE 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 THEN UPDATEmy_tree SETcounter = counter – 1 WHEREid = OLD.pid; END IF; IFcurrent_setting('user_vars.tree_delete') = 'levelup' THEN UPDATEmy_tree SETpid = OLD.pid WHERE pid = OLD.id; ELSIFcurrent_setting('user_vars.tree_delete') = 'root' THEN UPDATEmy_tree SETpid = 0 WHEREpid = OLD.id; ELSE IFOLD.counterIS NOT NULL AND OLD.counter > 0 THEN DELETE FROM my_treeWHEREpid = OLD.id; END IF; END IF; RETURN OLD; END; $body$ LANGUAGE 'plpgsql'; CREATE TRIGGER "my_tree_delete" AFTER DELETE ON "public"."my_tree" FOR EACH ROW EXECUTE 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_tree USING ( SELECTset_config('user_vars.tree_delete', 'root', TRUE) ) ASconf WHEREid = [item.id]; Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)
  • 117. Вопросы? Статьи по теме: http://doc.prototypes.ru/database/trees/ Сергей Томулевич Rambler, Москва, 2010 Карикатуры: Сергей Корсун Иерархические структуры в реляционных базах данных: Adjacency List (Смежные вершины)