Выберите предков и непосредственных потомков узла в дереве вложенных множеств, используя MYSQL - PullRequest
1 голос
/ 12 февраля 2010

Надеюсь, что некоторые из вас, эксперты MySQL, могут мне помочь.

У меня есть данные тега поиска, которые хранятся во вложенном наборе.

TABLE searchTags

searchTagID
searchTag
lft
rgt

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

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

Например, если это мой вложенный набор ...

                          1_tagA_22
     2_tagB1_11          12_tagB2_13           14_tagB3_21
3_taC1_4   5_taC2_10                                   15_tagC3_20
               6_tagD1_9                        16_tagD2_17    18_tagD3_19
                  7_tagE1_8

... и для моей поисковой стрелки у меня есть LIKE CONCAT ('%', 'tagc', '%'), я хотел бы вернуть что-то похожее на это:

searchTag   |   ancestors   |  immediateChildren
tagC1          tagB1,tagA       NULL
tagC2         tagB1,tagA       tagD1
tagC3          tagB3,tagA       tagD2,tagD3

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

Этот метод работает, но я чувствую, что это неэффективное решение, которое может взорваться рано или поздно. :) Мне интересно, есть ли лучший способ сделать это - то есть, есть ли способ объединить все это в одном операторе SELECT, который является более эффективным?

Любой совет будет высоко ценится.

Спасибо!

Ссылка: Я использую следующее, чтобы выбрать тег поиска и путь предков ...

    SELECT 

        node.searchTag, 

        GROUP_CONCAT(parent.searchTag 
        ORDER BY parent.lft DESC
        SEPARATOR '; ') AS ancestors 


    FROM 

        searchTags AS node,
        searchTags AS parent

    WHERE node.lft BETWEEN parent.lft AND parent.rgt
    AND parent.lft < node.lft
    AND node.searchTag LIKE CONCAT('%','tagc','%')
    GROUP BY node.searchTagID;

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

SELECT lft, rgt INTO @parent_left, @parent_right FROM searchTags WHERE searchTagID = $id;

SELECT 

    GROUP_CONCAT(child.searchTag SEPARATOR "; ") as searchTag

FROM searchTags AS child
LEFT JOIN searchTags AS ancestor ON
    ancestor.lft BETWEEN @parent_left+1 AND @parent_right-1 AND
    child.lft BETWEEN ancestor.lft+1 AND ancestor.rgt-1
WHERE
    child.lft BETWEEN @parent_left+1 AND @parent_right-1 AND
    ancestor.searchTagID IS NULL;

Ответы [ 2 ]

1 голос
/ 15 февраля 2013

Здесь - SQL-скрипта с решением.

SQL:

SELECT t0.title node
      ,GROUP_CONCAT(t5.title) children
      ,(SELECT GROUP_CONCAT(t6.title)
                    FROM Tree t6
                    WHERE t6.lft<t0.lft AND t6.rgt>t0.rgt
                    ORDER BY t6.lft) ancestors
FROM Tree t0
     LEFT JOIN
     (SELECT *
      FROM (SELECT t1.lft node
                  ,MAX(t2.lft) nodeparent
            FROM Tree t1
                 INNER JOIN
                 Tree t2 ON t1.lft>t2.lft AND t1.rgt<t2.rgt
            GROUP BY t1.lft) t3 
            LEFT JOIN
            Tree t4 ON t3.node=t4.lft) t5 ON t0.lft=t5.nodeparent
GROUP BY t0.title;

Предки являются довольно простым подзапросом в операторе select.

Для детей подзапрос t3 создает список смежности, находя предка каждого узла, имеющего MAX (lft), который затем соединяется с t4 для получения имени ребенка.

Не стесняйтесь помещать любое предложение WHERE внизу.

0 голосов
/ 12 февраля 2010

Прочитайте эти хорошие статьи о вложенных множествах в MySQL. http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/> http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

...