递归查询加速系统

Recursive query to speed up system

我的应用程序读取具有父子关系的 table。该应用程序自己查询树的每一层,它真的很慢(必须深入多层)。我一直在寻找另一种解决方案并进行了递归查询。对于我找到的示例,我无法将其映射到我的数据结构。

我的结构如下:

CREATE TABLE [products].[BillOfMaterial](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [parentNumber] [nvarchar](50) NOT NULL,
    [warehouse] [nvarchar](50) NOT NULL,
    [sequenceNumber] [int] NOT NULL,
    [childNumber] [nvarchar](50) NOT NULL,
    [childDescription] [nvarchar](50) NULL,
    [qtyRequired] [numeric](18, 3) NOT NULL,
    [childItemClass] [nvarchar](50) NULL,
    [childItemType] [nvarchar](50) NULL,
    [scrapFactor] [numeric](18, 3) NULL,
    [bubbleNumber] [int] NOT NULL,
    [operationNumber] [int] NOT NULL,
    [effectivityDate] [date] NULL,
    [discontinuityDate] [date] NULL,
    [companyID] [bigint] NOT NULL,
 CONSTRAINT [PK_BillOfMaterial] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

一些示例数据:

当我查询 parentNumber 1 时,它应该给我所有这些行:

对于 parentNumber 3,输出必须是:

现在我以递归方式需要父项的所有子项。我怎样才能仅使用 sql 来实现这一点? (我正在使用 SQL 服务器)

我已经尝试在 sql 中使用 with 语句,但它现在会给出很多结果。

WITH bom ( [id]
      ,[parentNumber]
      ,[warehouse]
      ,[sequenceNumber]
      ,[childNumber]
      ,[childDescription]
      ,[qtyRequired]
      ,[childItemClass]
      ,[childItemType]
      ,[scrapFactor]
      ,[bubbleNumber]
      ,[operationNumber]
      ,[effectivityDate]
      ,[discontinuityDate]
      ,[companyID] )
AS
(
    select * from [CR_ApplicationSuite].[products].[BillOfMaterial] where parentNumber IN ('F611882261', '2912435206')
UNION ALL
select b.* from [CR_ApplicationSuite].[products].[BillOfMaterial] b
INNER JOIN [CR_ApplicationSuite].[products].[BillOfMaterial] c on c.childNumber = b.parentNumber
)
SELECT *
FROM bom

这是一个使用 table 变量进行演示的示例。

对于递归查询,您需要在自身内部使用 CTE。

我包括了一个 rootParentNumber,所以更明显的是父级是什么。

WHERE 子句在示例中进行了注释。 因为您可以在递归查询中或在外部查询中放置 WHERE 子句。前者应该更快。

declare @BillOfMaterial  TABLE (
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [parentNumber] [nvarchar](50) NOT NULL,
    [warehouse] [nvarchar](50) NOT NULL,
    [sequenceNumber] [int] NOT NULL,
    [childNumber] [nvarchar](50) NOT NULL,
    [childDescription] [nvarchar](50) NULL,
    [qtyRequired] [numeric](18, 3) NOT NULL,
    [childItemClass] [nvarchar](50) NULL,
    [childItemType] [nvarchar](50) NULL,
    [scrapFactor] [numeric](18, 3) NULL,
    [bubbleNumber] [int] NOT NULL,
    [operationNumber] [int] NOT NULL,
    [effectivityDate] [date] NULL,
    [discontinuityDate] [date] NULL,
    [companyID] [bigint] NOT NULL
);

insert into @BillOfMaterial (parentNumber, childNumber, warehouse, sequenceNumber, qtyRequired, bubbleNumber, operationNumber, companyID) values
('1','2','WH1',1,0,0,0,1),
('2','4','WH1',2,0,0,0,1),
('3','4','WH1',3,0,0,0,1),
('4','5','WH1',4,0,0,0,1),
('5','0','WH1',5,0,0,0,1);

WITH BOM 
AS
(
    select parentNumber as rootParentNumber, * 
    from @BillOfMaterial 
    --where parentNumber IN ('1','3')

    union all

    select bom.rootParentNumber, b.* 
    from BOM
    INNER JOIN @BillOfMaterial b 
    on (BOM.childNumber = b.parentNumber and b.childNumber <> '0')
)
SELECT 
 [rootParentNumber]
,[parentNumber]
,[childNumber]
,[id]
,[warehouse]
,[sequenceNumber]
,[childDescription]
,[qtyRequired]
,[childItemClass]
,[childItemType]
,[scrapFactor]
,[bubbleNumber]
,[operationNumber]
,[effectivityDate]
,[discontinuityDate]
,[companyID]
FROM BOM
--WHERE rootParentNumber IN ('1','3')
ORDER BY [rootParentNumber], [parentNumber], [childNumber]
;