Действительно ли возможно запросить таблицу древовидной структуры в MySQL в едином запросе на глубину?

Другие ответили на это в разумной степени, но часто с именем «тернарный оператор».

Будучи педантом, которым я являюсь, я хотел бы четко указать, что имя оператора условный оператор или «условный оператор?:». Это a тернарный оператор (в том, что он имеет три операнда), и в настоящий момент он является единственным тернарным оператором в Java.

Однако спецификация довольно ясно , что его имя является условным оператором или «условным оператором?:», чтобы быть абсолютно однозначным. Я думаю, что более понятно назвать это именем, поскольку оно указывает на поведение оператора в некоторой степени (оценивая условие), а не только на количество его операндов.

58
задан Vertexwahn 4 March 2016 в 06:15
поделиться

6 ответов

Да, это возможно, это - названный Измененный Обход дерева Перед порядком, как лучше всего описано здесь

Деревья Joe Celko и Иерархии в SQL для Присяжных острословов

А, который рабочий пример (в PHP) обеспечивается здесь

http://www.sitepoint.com/article/hierarchical-data-database/2/

37
ответ дан Dave Cheney 7 November 2019 в 05:35
поделиться

Вот несколько ресурсов:

В основном, необходимо будет сделать своего рода курсор в хранимой процедуре или запросить или создать таблицу смежности. Я избежал бы рекурсии за пределами дб: в зависимости от того, как глубоко Ваше дерево, который мог стать действительно медленным/поверхностным.

23
ответ дан Paŭlo Ebermann 7 November 2019 в 05:35
поделиться

Я столкнулся с этой проблемой прежде и имел одну дурацкую идею. Вы могли сохранить поле в каждой записи, которая является сцепленной строкой, он - идентификаторы прямых предков полностью назад к корню.

Предполагают, что у Вас были записи как это (добавление отступа подразумевает иерархию, и числа являются идентификатором, предками.

  • 1, "1"
    • 2, "2,1"
        <литий> 5, "5,2,1" <литий> 6, "6,2,1"
          <литий> 7, "7,6,2,1" <литий> 11, "11,6,2,1"
    • 3, "3,1"
        <литий> 8, "8,3,1" <литий> 9, "9,3,1" <литий> 10, "10,3,1"

Тогда к [1 116] выбирает потомков id:6, просто делает это

SELECT FROM table WHERE ancestors LIKE "%6,2,1"

, Совершенствование столбца предков могло бы быть большей проблемой, чем это стоит Вам, но это - выполнимое решение в любом DB.

2
ответ дан Daniel Beardsley 7 November 2019 в 05:35
поделиться

Техника Celko (вложенные наборы) довольно хороша. Я также использовал таблицу смежности с полями "предок" и "потомок" и "расстояние" (например, у прямых детей/родителей есть расстояние 1, у внуков/бабушки и дедушки есть расстояние 2, и т.д.).

Это должно сохраняться, но довольно легко сделать для вставок: Вы используете транзакцию, затем помещаете прямую ссылку (родитель, ребенок, distance=1) в таблицу, затем ВСТАВЛЯЕТЕ, ИГНОРИРУЮТ ВЫБОР существующего parent& дети путем добавления расстояний (я могу потянуть SQL, когда у меня есть шанс), который хочет индекс на каждом из этих 3 полей для производительности. То, где этот подход становится ужасным, для удалений..., в основном необходимо отметить все объекты, которые были затронуты и затем восстанавливают их. Но преимущество этого состоит в том, что это может обработать произвольные графы без петель, тогда как вложенная модель набора может только сделать прямые иерархии (например, каждый объект кроме корня имеет одного и только одного родителя).

2
ответ дан Jason S 7 November 2019 в 05:35
поделиться

SQL не является полным по Тьюрингу языком, что означает, что Вы не собираетесь быть способными выполнить этот вид цикличного выполнения. Можно сделать некоторые очень умные вещи с SQL и древовидными структурами, но я не могу думать о способе описать строку, которая имеет определенный идентификатор "в его иерархии" для иерархии произвольной глубины.

Ваш лучший выбор - что-то вроде того, какой предложенный @Dan, который должен просто проложить себе путь через дерево в некотором другом, более способном языке. Можно на самом деле генерировать строку запроса на языке общего назначения с помощью цикла, где запрос является просто некоторой замысловатой серией соединений (или подзапросы), который отражает глубину иерархии, которую Вы ищете. Это было бы более эффективно, чем цикличное выполнение и несколько запросов.

1
ответ дан Daniel Spiewak 7 November 2019 в 05:35
поделиться

Вы почти определенно собираетесь хотеть использовать некоторую рекурсию для этого. И если бы Вы делаете это, тогда это было бы тривиально (на самом деле легче) для получения всего дерева, а не битов его на фиксированную глубину.

В действительно грубом псевдокоде Вы захотите что-то вдоль этих строк:

getChildren(parent){
    children = query(SELECT * FROM table WHERE parent_id = parent.id)
    return children
}

printTree(root){
    print root
    children = getChildren(root)
    for child in children {
        printTree(child)
    }
}

, Хотя на практике Вы редко хотели бы сделать что-то вроде этого. Это будет довольно неэффективно, так как это выполняет один запрос для каждой строки в таблице, таким образом, это только будет разумно или для маленьких таблиц или для деревьев, которые не вкладываются слишком глубоко. Честно говоря, в любом случае Вы, вероятно, хотите ограничить глубину.

Однако, учитывая популярность этих видов структуры данных, может быть некоторый материал MySQL, чтобы помочь Вам с этим, конкретно сократить числа запросов, которые необходимо сделать.

Редактирование: думая об этом, имеет очень мало смысла делать все эти запросы. Если Вы читаете всю таблицу так или иначе, то можно просто хлебать все это в RAM - предположение, что это является достаточно маленьким!

-1
ответ дан Dan 7 November 2019 в 05:35
поделиться
Другие вопросы по тегам:

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