Медленно и нерешительно продвигается портирование одной нашей разработки из-под Oracle на MS-SQL. Очередной маленькой победой стал перевод иерархического запроса в рекурсивный, почти совместимый с SQL 1999 (не считая слова RECURSIVE).
Итак, в Oracle все просто – дерево в реляционной форме представляется как таблица, которая связывает каждый узел с его родителем.
parent child comment
-----------------------------
0 1 Root
1 2 Level1
1 5 Level1
1 7 Level1
2 3 Level2
2 4 Level2
4 6 Level3
…
На самом деле, узлы могут идти в произвольном порядке. Чтобы обойти дерево последовательно, слева направо, достаточно отправить запрос следующего вида:
- SELECT parent, child, comment, level
- FROM tree
- CONNECT BY parent = PRIOR child
- START WITH parent = 0
Здесь level – идентификатор, которому сопоставляется текущий уровень иерархии, CONNECT BY указывает, по каким полям производится связывание, причем PRIOR определяет направление движения, а START WITH указывает на начало иерархии.
Результатом данного запроса будет следующая таблица.
parent child comment
-----------------------------
0 1 Root
1 2 Level1
2 3 Level2
2 4 Level2
4 6 Level3
1 5 Level2
1 7 Level2
…
Чтобы оформить те же действия для MS-SQL, строится следующий запрос.
- WITH
- Rec (child, parent, comment, level)
- AS (
- SELECT child, parent, comment, 0 AS level FROM tree WHERE parent = 0
- UNION ALL
- SELECT tree.child, tree.parent, tree.comment , level + 1
- FROM tree, Rec
- WHERE tree.parent = Rec.child
- )
- SELECT child, parent, comment, level FROM Rec
Я это понимаю так. С помощью фразы WITH мы строим новую таблицу Rec, из которой последний SELECT извлекает данные. Таблица Rec состоит из двух частей: корня иерархии (SELECT child, parent, comment, 0 AS level FROM tree where parent = 0), объединенного (UNION ALL) с преобразованным при помощи рекурсивного обхода телом базовой таблицы (второй SELECT). level приходится эмулировать базовыми средствами SQL.
Комментариев нет:
Отправить комментарий