用嵌套集编写SQL查询

时间:2012-02-27 07:51:03

标签: sql join mysqli subquery nested-sets

我需要编写一个查询来执行搜索,其中所有结果都与类别匹配 这些类别有子类别,它们作为嵌套集模型工作,每个类别都有一个lft和一个rgt列。

如果cat2cat3cat4cat1的孩子,那么他们的.lft {{1} }和cat1.lft

所有类别都存储在cat1.rgt表格中,并且CATEGORIES为主键。

我需要的是一个类别ID,查找ID表中属于该类别的所有项目,以及属于类别子类别的所有项目。

我正在寻找的查询将是这样的

ITEMS

我的意思是我得到类别主键( SELECT i.id, i.name FROM items AS i, categories AS c WHERE i.category_lft BETWEEN c.given_cat_id_lft AND c.given_cat_id_rgt ),但在查询中我需要使用他们的rgt和ltf值

我应该使用子查询还是加入? 查询应该如何? 我真的没有SQL的经验。

3 个答案:

答案 0 :(得分:1)

 SELECT i.id
      , i.name
 FROM items AS i
   JOIN categories AS c
     ON i.category_id = c.id
   JOIN categories AS myc
     ON c.category_lft BETWEEN myc.lft AND myc.rgt
 WHERE myc.id = @GivenCategoryID

答案 1 :(得分:0)

试试这个:

CREATE table #Category(
id      INT NOT NULL,
name    VARCHAR(20) NOT NULL,
parentid    INT NOT NULL
)

INSERT INTO #Category (id, name, parentid) VALUES
(1, 'parts', 1),
(2, 'processor', 1),
(3, 'AMD', 2),
(4, 'Intel', 2),
(5, 'Hard Disk', 1),
(6, 'Memory', 1),
(7, 'DDR1', 6),
(8, 'DDR2', 6),
(9, 'DDR3', 6),
(10, '533Mhz', 7),
(11, '667Mhz', 8),
(12, '800Mhz', 8)

CREATE table #Items(
id      INT NOT NULL,
name    VARCHAR(20) NOT NULL,
categoryId  INT NOT NULL
)

INSERT INTO #Items (id, name, categoryId) VALUES
(1, 'AMD Phenom', 3),
(2, 'AMD Sempron', 3),
(3, 'AMD Athlon', 3),
(4, 'Intel core 2 duo', 4),
(5, 'Intel core i3', 4),
(6, 'DDR2 1GB 6667Mhz', 11),
(7, 'Intel 8080', 4),
(8, 'Intel 80286', 4),
(9, 'Intel 80386', 4),
(10, 'Intel 80486', 4),
(11, 'Intel Pentuim', 4),
(12, 'Intel Pentium I', 4)


DECLARE @TopLevelId INT; -- top level category Id
SET @TopLevelId = 2;   -- top level category = AMD processors

WITH CTE AS
(SELECT id, name, parentid, id as Adam, 1 as level
FROM #Category
WHERE id = @TopLevelId
UNION ALL
SELECT #Category.id, #Category.name, #Category.parentid, CTE.Adam, CTE.level + 1
FROM #Category 
INNER JOIN CTE ON
    #Category.parentid = CTE.id
WHERE #Category.id <> @TopLevelId
)
SELECT CTE.id CategoryId, CTE.name as Category, #Items.name as Item
FROM CTE
INNER JOIN #Items ON
    CTE.id = #Items.categoryId
ORDER BY level, CTE.id


DROP table #Category
DROP table #Items

答案 2 :(得分:-1)

您将需要递归SQL来解决此问题。

首先找到所有具有给定类别的子类别,如父母,祖父母,祖父母,...(不要忘记包括给定的类别本身)。

然后使用Items表中的类别加入这些子类别。

我会忘记lft和rght值。做这项工作将是一项很糟糕的工作。 (BETWEEN将如何工作?基于Id的值?您能想象在现有子类别之间的某处插入子类别的后果吗?)