Сгладьте иерархию списка смежности к списку всех путей

https://docs.python.org/3/library/curses.html#module-curses

Модуль curses предоставляет интерфейс [115 ] в библиотеку проклятий

blockquote>

То есть вам нужна библиотека проклятий в вашей системе. Для перекомпиляции Python вам также понадобятся заголовочные (включающие) файлы из пакета разработки.

sudo yum install ncurses-devel

8
задан Aaron Hoffman 18 April 2009 в 23:39
поделиться

3 ответа

Выполнять многоуровневые запросы через простой список смежности всегда включает в себя само-левые соединения. Создать таблицу с выравниванием по правому краю легко:

SELECT category.category_id,
    ancestor4.category_id AS lvl4,
    ancestor3.category_id AS lvl3,
    ancestor2.category_id AS lvl2,
    ancestor1.category_id AS lvl1
FROM categories AS category
    LEFT JOIN categories AS ancestor1 ON ancestor1.category_id=category.category_id
    LEFT JOIN categories AS ancestor2 ON ancestor2.category_id=ancestor1.parent
    LEFT JOIN categories AS ancestor3 ON ancestor3.category_id=ancestor2.parent
    LEFT JOIN categories AS ancestor4 ON ancestor4.category_id=ancestor3.parent;

Выровнять по левому краю, как в вашем примере, немного сложнее. Это приходит на ум:

SELECT category.category_id,
    ancestor1.category_id AS lvl1,
    ancestor2.category_id AS lvl2,
    ancestor3.category_id AS lvl3,
    ancestor4.category_id AS lvl4
FROM categories AS category
    LEFT JOIN categories AS ancestor1 ON ancestor1.parent IS NULL
    LEFT JOIN categories AS ancestor2 ON ancestor1.category_id<>category.category_id AND ancestor2.parent=ancestor1.category_id
    LEFT JOIN categories AS ancestor3 ON ancestor2.category_id<>category.category_id AND ancestor3.parent=ancestor2.category_id
    LEFT JOIN categories AS ancestor4 ON ancestor3.category_id<>category.category_id AND ancestor4.parent=ancestor3.category_id
WHERE
    ancestor1.category_id=category.category_id OR
    ancestor2.category_id=category.category_id OR
    ancestor3.category_id=category.category_id OR
    ancestor4.category_id=category.category_id;

будет работать для n-уровневых иерархий.

Извините, запросы произвольной глубины невозможны в модели списка смежности. Если вы часто выполняете этот тип запроса, вам следует изменить свою схему на одну из других моделей хранения иерархической информации : полное отношение смежности (хранение всех отношений предок-потомок), материализованный путь или вложенный наборы.

Если категории не

11
ответ дан 5 December 2019 в 08:25
поделиться

Обход дерева произвольной глубины обычно включает в себя рекурсивный процедурный код, если вы не используете специальные функции некоторых СУБД.

В Oracle предложение CONNECT BY позволит вам в глубоком порядке пройти по дереву в первом порядке, если вы используете список смежности, как здесь.

Если вы используете вложенные наборы, левый порядковый номер предоставит вам порядок посещения узлов.

1
ответ дан 5 December 2019 в 08:25
поделиться

Как уже упоминалось, в SQL нет чистого способа реализации таблиц с динамически изменяющимся числом столбцов. Единственные два решения, которые я использовал ранее: 1. Фиксированное число Self-Joins, дающее фиксированное количество столбцов (AS на BobInce) 2. Сгенерируйте результаты в виде строки в одном столбце.

Второй изначально звучит гротескно; хранить идентификаторы в виде строки ?! Но когда выходные данные отформатированы как XML или что-то вроде этого, люди, похоже, не особо обращают на это внимание.

Точно так же это мало что дает, если вы затем захотите объединить результаты в SQL. Если результат должен быть представлен в приложении, он может быть очень подходящим. Лично я предпочитаю делать выравнивание в Приложении, а не в SQL


Я застрял здесь на 10-дюймовом экране без доступа к SQL, поэтому я не могу дать протестированный код, но основным методом было бы использовать рекурсию каким-либо образом;
- Рекурсивная скалярная функция может сделать это
- MS SQL может сделать это, используя рекурсивный оператор WITH (более эффективный).

Скалярная функция (что-то вроде):

CREATE FUNCTION getGraphWalk(@child_id INT)
RETURNS VARCHAR(4000)
AS
BEGIN

  DECLARE @graph VARCHAR(4000)

  -- This step assumes each child only has one parent
  SELECT
    @graph = dbo.getGraphWalk(parent_id)
  FROM
    mapping_table
  WHERE
    category_id = @child_id
    AND parent_id IS NOT NULL

  IF (@graph  IS NULL)
    SET @graph = CAST(@child_id AS VARCHAR(16))
  ELSE
    SET @graph = @graph + ',' + CAST(@child_id AS VARCHAR(16))

  RETURN @graph

END


SELECT
  category_id                         AS [category_id],
  dbo.getGraphWalk(category_id)       AS [graph_path]
FROM
  mapping_table
ORDER BY
  category_id

Я не использовал рекурсивный оператор WITH некоторое время, но я приведу синтаксис в порядок даже хотя у меня нет здесь SQL, чтобы что-то тестировать:)

Рекурсивный С

WITH
  result (
    category_id,
    graph_path
  )
AS
(
  SELECT
    category_id,
    CAST(category_id AS VARCHAR(4000))
  FROM
    mapping_table
  WHERE
    parent_id IS NULL

  UNION ALL

  SELECT
    mapping_table.category_id,
    CAST(result.graph_path + ',' + CAST(mapping_table.category_id AS VARCHAR(16)) AS VARCHAR(4000))
  FROM
    result
  INNER JOIN
    mapping_table
      ON result.category_id = mapping_table.parent_id
)

SELECT
  *
FROM
  result
ORDER BY
  category_id


РЕДАКТИРОВАТЬ - ВЫХОД для обоих одинаков:

1   '1'
2   '1,2'
3   '1,2,3'
4   '1,2,4'
5   '1,2,5'
6   '1,6'
7   '1,6,7'
8   '1,6,7,8'
9   '1,6,9'
8
ответ дан 5 December 2019 в 08:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: