我有这3张桌子
Products (Id, Name)
Products_Categories (ProductId, CategoryId)
Categories (Id, ParentCategoryId)
如你所见
Products
到Categories
是多对多的Category
可能有也可能没有父母(父母也是类别)如何在类别(包括其后代)
下创建选择所有(不同)产品的存储过程我想要的伪代码(不是LINQ):
Category c;
return c.GetSelfAndDescendants().Select(x => x.Products).Distinct();
我需要的是存储过程,例如
CREATE PROCEDURE [spAllProductsUnderCateg]
@categId int
AS
BEGIN
SET NOCOUNT ON;
-- This may be completely wrong
SELECT DISTINCT * FROM Products p
JOIN Products_Categories ON Products_Categories.ProductId = p.Id
WHERE...???
END
GO
答案 0 :(得分:1)
编辑:我以前无处接近。添加了功能示例
编辑2:更新了小提琴以获得更清晰的程序并更改了代码以反映正确的解决方案
这个问题需要一个递归过程来深入挖掘后代树的未知深度。这有可能是一个非常昂贵的操作,如果两个类别互相称为父母,这里的设计也可能导致无限循环,所以你可能想要加入一些保护措施。
我使用临时表来收集所有不同查询的结果,然后使用调用递归过程的过程返回它们,因此所需要的只是调用spAllProductsUnderCateg来返回结果集。
CREATE PROCEDURE [spAllProductsUnderCateg]
@categId int
AS
BEGIN
CREATE TABLE #ProductsByCategory (Name varchar(100))
-- This may be completely wrong
INSERT INTO #ProductsByCategory
SELECT DISTINCT p.Name FROM Products p
JOIN Products_Categories pc ON pc.ProductId = p.Id
WHERE pc.CategoryId = @categId
EXEC spGetChildCategories @categId
SELECT DISTINCT * FROM #ProductsByCategory
END
GO
CREATE PROCEDURE [spGetChildCategories]
@categId int
AS
BEGIN
DECLARE @nextCatId int
DECLARE cur CURSOR LOCAL
FOR SELECT DISTINCT Id FROM Categories
WHERE ParentCategoryId = @categId
OPEN cur
FETCH NEXT FROM cur INTO @nextCatId
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #ProductsByCategory
SELECT DISTINCT p.Name FROM Products p
JOIN Products_Categories pc ON pc.ProductId = p.Id
WHERE pc.CategoryId = @nextCatId
EXEC spGetChildCategories @nextCatId
FETCH NEXT FROM cur INTO @nextCatId
END
CLOSE cur
END
GO
我在PL / SQL方面比T-SQL更有经验,但这在小提琴中起作用。由于它使用了递归,游标和额外的表,你肯定会想要评估它的性能限制,但它确实可以处理我提供的数据。