Список смежности при холодном слиянии - PullRequest
1 голос
/ 23 июня 2011

Это изображение демонстрирует то, чего я пытаюсь достичь.Слева находятся данные таблицы, справа таблица, которую я пытаюсь создать.

таблица использует parentID для ссылки на другой элемент в той же таблице для создания иерархии.

Как мне создать запросы и организовать их таким образом?

Что если я выберу «Пираты» и захочу получить всех родителей?Есть ли что-нибудь в CFML, что делает это проще, чем зацикливание запросов, пока я не доберусь до вершины?

enter image description here

Ответы [ 4 ]

2 голосов
/ 23 июня 2011

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

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

1 голос
/ 23 июня 2011

Я не проверял это ...:)

<!--- item.cfc --->
<cfcomponent persistent="true" cache="read-only">
    <cfproperty name="id" fieldtype="id">
    <cfproperty name="parent"
                fieldtype="many-to-one" cfc="item" fkcolumn="ParentID">
    <cfproperty name="children" type="array"
                fieldtype="one-to-many" cfc="item" fkcolumn="ParentID" inverse="true">
</cfcomponent>

<!--- display.cfm --->
<cffunction name="printItem" output="true">
    <cfargument name="item" required="true">
    <table>
        <tr>
        <td>#item.getName()#

        <cfif item.hasChildren()>
            <table>
              <cfloop array="#item.getChildren()#" index="local.i">
                  <tr>
                      <td>#printItem(local.i)#
              </cfloop>
            </table>
        </cfif>
    </table>
</cffunction>

<cfset printItem( entityLoadByPK("item",1) )>
0 голосов
/ 24 июня 2011

Вот что я придумал с вашей помощью.

<!--- adjacency list display --->
<cffunction name="adjacentList" output="true">
    <cfargument name="alQuery" required="true">
    <cfargument name="qid" required="false" default="0">

        <cfquery name="alSubQuery" dbtype="query">
            SELECT * FROM alQuery WHERE parentID=#qid#
        </cfquery>

        <cfif alSubQuery.RecordCount neq 0>
            <ul>
            <cfloop query="alSubQuery">
                <li>
                #name#
                #adjacentList(#alQuery#,#id#)#
                </li>
            </cfloop>
            </ul>
        </cfif>
</cffunction>

используя: #adjacentList(#query#)#

0 голосов
/ 23 июня 2011

Один из подходов, который я рассмотрел при рассмотрении аналогичной потребности, заключается в асинхронном построении иерархии, то есть с помощью запросов AJAX.В зависимости от ваших потребностей, это может работать, а может и не работать, но представьте, что вместо немедленного построения целого дерева вы сначала предоставляете пользователю только верхний уровень.Затем, когда пользователь выбирает один из элементов верхнего уровня, делается запрос AJAX, чтобы найти дочерние элементы выбранного элемента.Повторите по мере необходимости для каждого ребенка, чтобы построить дерево.С этой целью проблема очень проста, и запросы и код, используемый для ее реализации, также очень просты.

...