Для простой структуры данных, такой как:
ID parentID Text Price
1 Root
2 1 Flowers
3 1 Electro
4 2 Rose 10
5 2 Violet 5
6 4 Red Rose 12
7 3 Television 100
8 3 Radio 70
9 8 Webradio 90
Для справки дерево иерархии выглядит так:
ID Text Price
1 Root
|2 Flowers
|-4 Rose 10
| |-6 Red Rose 12
|-5 Violet 5
|3 Electro
|-7 Television 100
|-8 Radio 70
|-9 Webradio 90
Я хочу посчитать количество детей на уровне. Итак, я бы получил новый столбец «NoOfChildren» вот так:
ID parentID Text Price NoOfChildren
1 Root 8
2 1 Flowers 3
3 1 Electro 3
4 2 Rose 10 1
5 2 Violet 5 0
6 4 Red Rose 12 0
7 3 Television 100 0
8 3 Radio 70 1
9 8 Webradio 90 0
Я читал кое-что об иерархических данных, но почему-то застрял на нескольких внутренних соединениях по родительским идентификаторам. Может, здесь кто-нибудь сможет мне помочь.
2 ответа
Использование CTE даст вам то, что вы хотите. сильный>
- Рекурсивно перебрать всех дочерних элементов, запомнив корень.
COUNT
элементы для каждого корня.JOIN
это снова с исходной таблицей для получения результатов.
Тестовые данные
DECLARE @Data TABLE (
ID INTEGER PRIMARY KEY
, ParentID INTEGER
, Text VARCHAR(32)
, Price INTEGER
)
INSERT INTO @Data
SELECT 1, Null, 'Root', NULL
UNION ALL SELECT 2, 1, 'Flowers', NULL
UNION ALL SELECT 3, 1, 'Electro', NULL
UNION ALL SELECT 4, 2, 'Rose', 10
UNION ALL SELECT 5, 2, 'Violet', 5
UNION ALL SELECT 6, 4, 'Red Rose', 12
UNION ALL SELECT 7, 3, 'Television', 100
UNION ALL SELECT 8, 3, 'Radio', 70
UNION ALL SELECT 9, 8, 'Webradio', 90
Заявление SQL
;WITH ChildrenCTE AS (
SELECT RootID = ID, ID
FROM @Data
UNION ALL
SELECT cte.RootID, d.ID
FROM ChildrenCTE cte
INNER JOIN @Data d ON d.ParentID = cte.ID
)
SELECT d.ID, d.ParentID, d.Text, d.Price, cnt.Children
FROM @Data d
INNER JOIN (
SELECT ID = RootID, Children = COUNT(*) - 1
FROM ChildrenCTE
GROUP BY RootID
) cnt ON cnt.ID = d.ID
WITH
, определяющее CTE
, может смешиваться с предложением WITH
, которое определяет подсказку таблицы. Первый оператор следует явно разделять точкой с запятой, если он не является первым оператором в пакете.
;WITH
, и у вас никогда не будет проблем (как в коде @ Lieven)
SELECT ... FROM ... OPTION (MAXRECURSION 200)
Рассмотрите возможность использования модифицированного способа обхода дерева предварительного заказа для хранения иерархических данных. См. http://www.sitepoint.com/hierarchical-data-database/.
Тогда определение количества дочерних элементов для любого узла становится простым:
SELECT (right-left-1) / 2 AS num_children FROM ...
Похожие вопросы
Связанные вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.