Как получить все родительские и дочерние категории, к которым относится каждый продукт? - PullRequest
3 голосов
/ 03 декабря 2010

У меня есть 3 таблицы:

CREATE TABLE [dbo].[ProductCategory](
 [categoryID] [int] IDENTITY(1,1) NOT NULL,
 [categoryParentID] [int] NULL,
 [categoryName] [nvarchar](200) NOT NULL
)

CREATE TABLE [dbo].[Product]
(
 [productID] [bigint] IDENTITY(1,1) NOT NULL,
 [productName] [nvarchar(100)] NOT NULL,
 .
 .
)

CREATE TABLE [dbo].[ProductToCategoryLink]
(
 [productID] [bigint] NOT NULL,
 [categoryID] [int] NOT NULL
)

Пример данных примера:

Продукт:

1, 'Book_1 ';

2,' Book_2 ';

Категория продукта:

1, NULL,' Книги ';

2, 1, 'Подкатегория книг lvl_1';

3, 2, 'Подкатегория книг lvl_2';

4, 3, 'Подкатегория книг lvl_3';

ProductToCategoryLink:

1, 4;

2, 2;

Вопрос: Как получить все родительские и дочерние категории, к которым относится каждый продукт?

Итак, мне нужно получить что-то вроде этого:


productID, productName, categoryID, categoryName

1, 'Book_1', 1, 'Книги ';

1,' Book_1 ', 2,' Подкатегория книг lvl_1 ';

1,' Book_1 ', 3,' Подкатегория книг lvl_2 ';

1, 'Book_1', 4, 'Подкатегория книг lvl_3';

2, 'Book_2', 1, 'Книги';

2, 'Book_2', 2, 'Подкатегория книг lvl_1';

Ответы [ 2 ]

3 голосов
/ 03 декабря 2010

Самый простой способ - через обычные табличные выражения.> Ссылка <</a>

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

1 голос
/ 05 декабря 2010

SQL-запрос, представленный в нижней части этого поста, должен помочь, если многословно.

Ключевой особенностью является рекурсивное определение табличного выражения иерархия . Первый SELECT извлекает все ссылки на товарные категории, а также их имена и идентификаторы родительских категорий. Это базовый случай рекурсии. Второй SELECT находит все родительские строки категории для всех строк, найденных на предыдущем шаге. Обратите особое внимание, что второй SELECT снова присоединяется к выражению иерархия , что делает запрос рекурсивным. SQL Server будет повторно оценивать второй SELECT, пока не будут найдены новые записи. Третий оператор SELECT просто возвращает результаты.

Как и следовало ожидать, было бы плохо, если бы в цепочке родительских категорий были циклы. SQL Server ограничивает количество повторений до того, как он откажется от запроса. Предельное значение по умолчанию - 100, что, вероятно, достаточно, если иерархия категорий не слишком велика. При необходимости вы можете увеличить его до 32767, используя опцию запроса MAXRECURSION.

Вот запрос SQL:

WITH
  hierarchy AS (
    SELECT
      prod.productId
    , prod.productName
    , cat.categoryId
    , cat.categoryParentId
    , cat.categoryName
    FROM dbo.ProductToCategoryLink AS link
    INNER JOIN dbo.Product AS prod
      ON prod.productId = link.productId
    INNER JOIN dbo.ProductCategory AS cat
      ON cat.categoryId = link.categoryId
    UNION ALL
    SELECT
      child.productId
    , child.productName
    , parent.categoryId
    , parent.categoryParentId
    , parent.categoryName
    FROM hierarchy AS child
    INNER JOIN dbo.ProductCategory AS parent
      ON parent.categoryId = child.categoryParentId
  )
SELECT
  productId
, productName
, categoryId
, categoryName
FROM hierarchy
ORDER BY
  productId
, categoryId
...