Самореферентная таблица и рекурсивная функция SQL - PullRequest
3 голосов
/ 15 сентября 2010

У меня есть таблица категорий с:

  • categoryID
  • parentCategoryID
  • categoryName

и таблица элементов с:

  • itemID
  • categoryID
  • itemName

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

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

Ответы [ 4 ]

2 голосов
/ 15 сентября 2010

Как вы застряли на этой схеме?Он называется «Список смежности», и концептуально он достаточно прост, но у него есть некоторые реальные недостатки.Наиболее важным из них является невозможность запроса для всех потомков.

Взгляните на это и подумайте, может ли альтернативный способ представления деревьев подойти вам:

http://pugs.postgresql.org/files/ModelingTrees.pdf

0 голосов
/ 15 сентября 2010

Если вы рассматриваете альтернативные подходы, описанные в документе , на который ссылается Jeff Dege , к вашей текущей структуре дерева списка смежности:

Вложенные наборы очень быстры для данных, которые часто читаются, но изменяются редко (для чтения используется SQL BETWEEN и индексы; изменения могут быть дорогостоящими, поскольку им может потребоваться обновить многие существующие записи), в то время как Перечисление пути (также известный как Материализованный путь ) обеспечивает приемлемую и хорошую производительность чтения при использовании индексов и LIKE '[path]%' запросов (по крайней мере для MySQL, насколько я знаю) и хорошую производительность для вставки операции и приемлемая производительность при перемещении категории в другую категорию.

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

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

0 голосов
/ 15 сентября 2010

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

Если предположить, что вы разрешаете прикреплять элементы только к «более низкой» категории, то что-то вродеполучите нужные вам результаты:

SELECT top.categoryID, top.categoryName, bottom.categoryID, bottom.categoryName,
    COUNT (items.itemID)
FROM categories AS top
LEFT JOIN categories AS bottom ON top.categoryID = bottom.parentCategoryID
LEFT JOIN items ON bottom.categoryID = items.categoryID
WHERE (bottom.categoryID = $your_category)
GROUP BY top.categoryID, bottom.categoryID

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

0 голосов
/ 15 сентября 2010

конечно возможно, но не очень эффективно.Вы должны использовать вложенные множества структур: http://intelligent -enterprise.informationweek.com / 001020 / celko1_1.jhtml; jsessionid = AFUXE0ZF4PTNXQE1GHPSKH4ATMY32JVN

, если вы не хотите, чтобы вы смотрели здесь:взгляд на это: http://explainextended.com/2010/04/18/hierarchical-query-in-mysql-limiting-parents/

...