Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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 Server:对两个不显示层次关系的条件逻辑的递归高级查询_Sql_Sql Server_Tsql_Sql Server 2012_Common Table Expression - Fatal编程技术网

SQL Server:对两个不显示层次关系的条件逻辑的递归高级查询

SQL Server:对两个不显示层次关系的条件逻辑的递归高级查询,sql,sql-server,tsql,sql-server-2012,common-table-expression,Sql,Sql Server,Tsql,Sql Server 2012,Common Table Expression,最近,我在SQL Server 2012中遇到了一个需要解决的难题。这就是问题的背景 我们在产品实体中维护一个自引用实体(层次结构)。每种产品都有亲子关系 产品具有称为主产品的特殊分组,主产品基于以下逻辑派生 如果在层次结构上只有一个产品,不管 ISMASTEMPRODCUT/标志,它都要考虑主帐户。 P. >其他产品,其直接母产品标注为主产品或最优先考虑的主要产品。 图形表示如下: 这是DDL -- Create Table CREATE TABLE Product ( Prod

最近,我在SQL Server 2012中遇到了一个需要解决的难题。这就是问题的背景

我们在产品实体中维护一个自引用实体(层次结构)。每种产品都有亲子关系

产品具有称为主产品的特殊分组,主产品基于以下逻辑派生

如果在层次结构上只有一个产品,不管<代码> ISMASTEMPRODCUT/<代码>标志,它都要考虑主帐户。

<> P. >其他产品,其直接母产品标注为主产品或最优先考虑的主要产品。

图形表示如下:

这是DDL

-- Create Table 
CREATE TABLE Product
(
    ProductID int PRIMARY KEY,
    Name      VARCHAR(30) NOT NULL,
    ParentId  int,
    IsMasterProdcut bit NOT NULL
)

-- Insert the data to the table 
-- Senario where top most product is the master product 
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (1,'Prodcut 1',NULL,0); -- <-- this is the master prodcut as non of the child as flaged
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (2,'Prodcut 2',1,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (3,'Prodcut 3',2,0);

-- Senario two where in middnle account has flag as master product 
INSERT INTO Product (ProductID,name,ParentId,IsMasterProdcut) VALUES (4,'Prodcut 4',NULL,0); -- <-- this is the master prodcut as this is top most in hirerachy . So 4 will be master prodcut of 4 and 5 , 6 and 7 will not master product
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (5,'Prodcut 5',4,0);  
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (6,'Prodcut 6',5,1); -- < -- this a a master prodcut as it is flagged as master product , So account 7 and 6 master product with be 6
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (7,'Prodcut 7',6,0);

-- Senario three where it has one product 
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (8,'Prodcut 8',0,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (9,'Prodcut 9',0,1);

-- Senario 4 Complex product 

INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (10,'Prodcut 10',0,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (11,'Prodcut 11',10,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (12,'Prodcut 12',11,1);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (13,'Prodcut 13',12,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (14,'Prodcut 14',10,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (15,'Prodcut 15',14,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (16,'Prodcut 16',15,0);
INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) VALUES (17,'Prodcut 17',10,0);
工作解决方案:这是我目前得到的解决方案:

      BEGIN 

    CREATE TABLE #TmpMasterProduct
    (
       ProductId nvarchar(50)
    )

    INSERT INTO #TmpMasterProduct
    SELECT ProductId

    FROM (
        -- Get master accounts which are flagged as master product  
        SELECT MA.ProductId 
        FROm [dbo].[Product] AS MA WITH (NOLOCK) 
        WHERE MA.[IsMasterProdcut] = 1

        UNION
        -- Get top most prodcut which will be automatically consider as master product.

        SELECT MAT.ProductId 
        FROM DBO.[Product] As MAT WITH (NOLOCK) 
        WHERE MAT.[ParentId] IS NULL
    ) AS MasterProdcuts;


    WITH Mapping as
    (
      SELECT A.ProductId , A.ParentId
      FROM DBO.[Product] A
      WHERE  A.ProductId IN 
      (
        SELECT ProductId 
        FROM #TmpMasterProduct
      )

      UNION ALL

      SELECT A.ProductId , A.ParentId
      FROM DBO.[Product]  A
      INNER JOIN Mapping M
      ON M.ProductId = A.ParentID
     )


    SELECT  M.ParentId As MasterProductId ,  MP.Name As MasterProductName , M.ProductId As ProdcutId , CP.Name As ProductName
    From Mapping As M
    LEFT OUTER JOIN DBO.Product As MP ON MP.ProductId = M.ParentId 
    LEFT OUTER JOIN DBO.Product As CP On CP.ProductId = M.ProductId

    DROP TABLE #TmpMasterProduct

END 
但我偏离了我想要的结果。这是我得到的电流输出

MasterProductId MasterProductName   ProdcutId   ProductName
NULL               NULL               1           Prodcut 1
NULL               NULL               4           Prodcut 4
5                  Prodcut 5          6           Prodcut 6
0                  NULL               9           Prodcut 9
11                 Prodcut 11         12          Prodcut 12
12                 Prodcut 12         13          Prodcut 13
6                  Prodcut 6          7           Prodcut 7
4                  Prodcut 4          5           Prodcut 5
5                  Prodcut 5          6           Prodcut 6
6                  Prodcut 6          7           Prodcut 7
1                  Prodcut 1          2           Prodcut 2
2                  Prodcut 2          3           Prodcut 3
基本上,我写的这个查询并没有深入到更深的层次。它从父级终止。我的第二个观察结果是,这确实拾取了不是主产品的父节点


我的方法错了吗?除了光标,我能做的最好的方法是什么

您走在正确的轨道上:)一些修复:

您在产品8和10中插入零,而不是null,如
ParentId
-这就是为什么在初始
#TmpMasterProduct
查询中从未提取它们-您需要将它们更改回null,例如

INSERT INTO Product (ProductID,Name,ParentId,IsMasterProdcut) 
VALUES (8,'Prodcut 8',NULL,0);
(另外,如果您在自联接上使用来自
ParentId->ProductId
的外键强制引用完整性,则可以防止此类问题)

您不需要主产品预滤器上的
接头
-您只需使用
,即:

INSERT INTO #TmpMasterProduct
SELECT MA.ProductId
FROM 
    [dbo].[Product] AS MA
WHERE MA.[IsMasterProdcut] = 1 OR MA.[ParentId] IS NULL;
在递归CTE中,您需要记住每个主产品树的实际
主产品ID
,而不一定是
父产品ID
,以允许层次结构大于1深,即

WITH Mapping as
(
  SELECT A.ProductId as MasterProductId, A.ProductId , A.ParentId ...

  UNION ALL

  SELECT M.MasterProductId, A.ProductId , A.ParentId ...
您需要在导航树时引入一个终止条件,当有一个节点本身是主产品时,该树终止(这将单独列出)

您需要按
MasterProductId
订购项目,以便将它们打印出来


您试图通过查询解决的实际问题是什么?我无法从您的描述中非常清楚地理解。@shree.pat18我正在尝试完成主产品到产品的映射,但我遇到的问题是,由于主产品派生逻辑有点复杂,我无法从sql中处理它。我目前正在使用C夏普来做这件事。实际上,看起来您想要的订单可能只是
ProductId
。您还可以使用附加的CTE完全避免使用#Temp表。谢谢,这就是我要找的。现在,我将尝试我的实际数据。
WITH Mapping as
(
  SELECT A.ProductId as MasterProductId, A.ProductId , A.ParentId ...

  UNION ALL

  SELECT M.MasterProductId, A.ProductId , A.ParentId ...
AND A.IsMasterProdcut = 0