Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择类别及其子体中的项的存储过程_Sql_Sql Server_Stored Procedures - Fatal编程技术网

Sql 选择类别及其子体中的项的存储过程

Sql 选择类别及其子体中的项的存储过程,sql,sql-server,stored-procedures,Sql,Sql Server,Stored Procedures,我有这三张桌子 Products (Id, Name) Products_Categories (ProductId, CategoryId) Categories (Id, ParentCategoryId) 如你所见 产品到类别是多对多 类别可能有父类,也可能没有父类(父类也是类别) 如何创建一个存储过程来选择类别(包括其子类)下的所有(不同的)产品 我想要的伪代码示例(不是LINQ): Category c; return c.GetSelfAndDescendants().Sele

我有这三张桌子

Products (Id, Name)
Products_Categories (ProductId, CategoryId)
Categories (Id, ParentCategoryId)
如你所见

  • 产品
    类别
    是多对多
  • 类别
    可能有父类,也可能没有父类(父类也是类别)
如何创建一个存储过程来选择类别(包括其子类)下的所有(不同的)产品

我想要的伪代码示例(不是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

Edit:我以前根本就不了解。添加了功能示例小提琴

Edit2:更新fiddle以获得更清晰的过程,并更改代码以反映正确的解决方案

这个问题需要一个递归过程来深入挖掘后代树的未知深度。这可能是一个非常昂贵的操作,如果两个类别将彼此称为父类,那么这里设计的操作也可能导致无限循环,因此您可能需要针对这一情况提供一些保护

我使用一个临时表来收集所有不同查询的结果,然后用调用递归过程的过程返回结果,所以只需要调用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方面更有经验,但这是非常有效的。由于它使用递归、游标和一个额外的表,您肯定会想评估它的性能限制,但它确实可以处理我提供给它的数据


你好,谢谢,但事情并没有那么简单。我还需要包括该类别的子类别中的所有产品。这就是我遇到的问题。多个子代级别将需要一个递归过程,该过程将调用自身来检索每个级别的子代。我得准备一把小提琴才能把它弄到手。我看看我能做什么。我很抱歉误解了您的要求。添加了一个功能示例链接到小提琴。哇,非常感谢小提琴!我想如果你把相关的代码粘贴到stackoverflow上也会很好。不客气。我在这里更新了代码,并稍微调整了小提琴,因此该过程直接使用临时表返回结果。