Рекурсивный выбор через 2 таблицы в SQL Server - PullRequest
2 голосов
/ 19 июня 2019

Для производственного отчета в SSRS мне необходимо отобразить базовый материал в нашей ERP, который может состоять из нескольких уровней.

У меня есть элементы в таблице INVENTPRODMETHOD, имеющие поле ProdMethodId, это относится к таблице INVENTPRODSUPPITEMSс «вспомогательными предметами».Основываясь на ProdMethodId, найденном в первой таблице, я получаю SUPPLITEMID, который мне нужен, чтобы узнать, какой ProdMethodId для этого (нового) элемента находится в первой таблице INVENTPRODMETHOD, и т. Д., И т. Д. Надеюсь, вы можете следовать за мной…

Мое требование - знать базовый материал на самом низком уровне.Например:

Я хочу найти базовый материал для элемента 100. В таблице DMO_INVENTPRODMETHOD я вижу, что PRODMETHODID = A123

В DMO_INVENTPRODSUPPITEMS он говорит мне, что этот PRODMETHODID A123 имеет SUPPLITEMIDS200

Теперь мне нужно сделать то же самое, но теперь для S200.В DMO_INVENTPRODMETHOD я получаю PRODMETHODID E123, когда смотрю, что в DMO_INVENTPRODSUPPITEMS SUPPLITEMID имеет значение S400

S400 в DMO_INVENTPRODMETHOD имеет PRODMETHODID Z123 *, но PRODMETID Z123 * не знает, что * PROVETHOID * знает, * DMI_NOWID * не знаюищите ITEMID в таблице DMO_INVENTPRODBASEITEMS с PRODMETHODID Z123

CREATE TABLE DMO_INVENTPRODMETHOD (
    ITEMID VARCHAR (10) NOT NULL,
    PRODMETHODID VARCHAR (10) NOT NULL,
);

INSERT INTO [dbo].[DMO_INVENTPRODMETHOD] VALUES ('100', 'A123')
INSERT INTO [dbo].[DMO_INVENTPRODMETHOD] VALUES ('S200', 'E123')
INSERT INTO [dbo].[DMO_INVENTPRODMETHOD] VALUES ('S400', 'Z123')



CREATE TABLE DMO_INVENTPRODSUPPITEMS (
    SUPPLITEMID VARCHAR (10) NOT NULL,
    PRODMETHODID VARCHAR (10) NOT NULL,
);

INSERT INTO [dbo].[DMO_INVENTPRODSUPPITEMS] VALUES ('S200', 'A123')
INSERT INTO [dbo].[DMO_INVENTPRODSUPPITEMS] VALUES ('S400', 'E123')


CREATE TABLE DMO_INVENTPRODBASEITEMS (
    ITEMID VARCHAR (10) NOT NULL,
    PRODMETHODID VARCHAR (10) NOT NULL,
);
INSERT INTO [dbo].[DMO_INVENTPRODBASEITEMS] VALUES ('BAAAB10', 'Z123')

Майк

1 Ответ

2 голосов
/ 22 июня 2019

Вот один из способов решить эту проблему.

Во-первых, нормализовать значения в таблицу Parent / Child. Затем выполните стандартную рекурсивную процедуру для нормализованных данных. Наконец, в обратном порядке, чтобы получить последний потомок в цепочке.

Sql Fiddle

DECLARE @DMO_INVENTPRODMETHOD  TABLE(ITEMID  VARCHAR (10) NOT NULL,PRODMETHODID VARCHAR (10) NOT NULL)
INSERT INTO @DMO_INVENTPRODMETHOD VALUES ('100', 'A123'),('S200', 'E123'),('S400', 'Z123')

DECLARE @DMO_INVENTPRODSUPPITEMS TABLE(SUPPLITEMID  VARCHAR (10) NOT NULL,PRODMETHODID  VARCHAR (10) NOT NULL)
INSERT INTO @DMO_INVENTPRODSUPPITEMS VALUES ('S200', 'A123'),('S400', 'E123')

DECLARE @DMO_INVENTPRODBASEITEMS TABLE(ITEMID VARCHAR (10) NOT NULL,PRODMETHODID VARCHAR (10) NOT NULL)
INSERT INTO @DMO_INVENTPRODBASEITEMS VALUES ('BAAAB10', 'Z123')

DECLARE @ITEMID NVARCHAR(10) = '100'

;WITH CombinedData AS
(
    SELECT DataLevel=1, ParentID=ITEMID, ChildID=PRODMETHODID  FROM @DMO_INVENTPRODMETHOD
    UNION
    SELECT DataLevel=2, ParentID=PRODMETHODID ,ChildID=SUPPLITEMID  FROM @DMO_INVENTPRODSUPPITEMS
    UNION
    SELECT DataLevel=3, ParentID=PRODMETHODID ,ChildID=ITEMID  FROM @DMO_INVENTPRODBASEITEMS
) 
,RecursiveWalk AS
 (
    SELECT  ParentID, ChildID,Level=1 FROM CombinedData WHERE  DataLevel=1 AND ParentID=@ITEMID

    UNION ALL

    SELECT D.ParentID,D.ChildID, Level=R.Level+1
    FROM
        RecursiveWalk R
        INNER JOIN  CombinedData D ON D.ParentID=R.ChildID
)
,ResultReverseOrdered AS
(
    SELECT *, RowNumber = ROW_NUMBER() OVER(ORDER BY Level DESC) FROM RecursiveWalk
)
SELECT
    PRODMETHODID = ParentID,
    Level 
FROM    
    ResultReverseOrdered
WHERE
    RowNumber = 1
...