SQL Сервер - Ошибка рекурсии - Поиск ошибочных данных - PullRequest
0 голосов
/ 26 мая 2020

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

with 
extension_table as (
    select
      dc_x_str_03 as warehouse
    , dc_x_str_04 as product
    , dc_x_str_10 as stk_class
    from extension_table with (nolock)
),
stock as (
    select
       a.warehouse
    , a.product
    , long_description
    , stk_class
    from stock a with (nolock)
    inner join extension_table b
    on a.warehouse = b.warehouse
    and a.product = b.product

    union all

    select 
      '' as warehouse
    , code as product
    , long_description
    , '' as stk_class
    from services_table with (nolock)
),
relationship_table as (
    select 
      assembly_warehouse
    , product_code
    , usage_quantity
    , component_whouse
    , component_code
    , b.stk_class
    , kind
    from relationship_table a with (nolock)
    left join extension_table b 
    on a.component_whouse=b.warehouse
    and a.component_code=b.product
),
extension_table_relationship as (
    select
      a.warehouse            as assembly_warehouse
    , a.product                as product_code
    , 1                        as usage_quantity
    , b.warehouse            as component_whouse
    , b.product                as component_code
    , b.stk_class            as stk_class
    , 'P'                    as kind
    from extension_table a
    inner join extension_table b
    on a.product = b.product
    where ( b.stk_class like 'MT%' or b.stk_class like 'PT%') 
    and a.stk_class like 'TT%'
),
relationship_union as (
    select * from extension_table_bom
    union all
    select * from relationship_table
),
relationship_run as (
SELECT
  warehouse as assembly_warehouse
, product as assembly_code
, cast(1 as float) as usage_quantity
, warehouse as component_warehouse
, product as component_code
, stk_class
, cast('P' as char(1)) as kind
, cast(warehouse as char(2)) as assy_wh1
, cast(product as char(20)) as assy_pr1
, cast(warehouse as char(2)) as assy_wh
, cast(product as char(20)) as assy_pr
, 1    as level
, CAST(    '->' + RTRIM(warehouse) + RTRIM(product) AS NVARCHAR(MAX)) AS matpath
FROM stock

union all

SELECT
  relationship_run.assembly_warehouse
, relationship_run.assembly_code
, cast(relationship_run.usage_quantity * relationship_union.usage_quantity as float) as usage_quantity
, stock.warehouse as component_warehouse
, stock.product as component_code
, stock.stk_class
, cast(relationship_union.kind as char(1))as [kind]
    , cast(relationship_union.assembly_warehouse as char(2)) as assy_wh1
    , cast(relationship_union.product_code as char(20)) as assy_pr1
    , case    when cast(    (select assembly_warehouse 
                        from relationship_table 
                        where component_whouse=stock.warehouse 
                        and component_code=stock.product
                        and assembly_warehouse=relationship_union.assembly_warehouse 
                        and product_code=relationship_union.product_code) as char(2)) IS NULL then 
                                                                                cast(    (select assembly_warehouse 
                                                                                        from relationship_table 
                                                                                        where component_whouse=relationship_union.assembly_warehouse 
                                                                                        and component_code=relationship_union.product_code
                                                                                        and assembly_warehouse=relationship_run.assy_wh1
                                                                                        and product_code=relationship_run.assy_pr1) as char(2))
            else cast(    (select assembly_warehouse 
                        from relationship_table 
                        where component_whouse=stock.warehouse 
                        and component_code=stock.product
                        and assembly_warehouse=relationship_union.assembly_warehouse 
                        and product_code=relationship_union.product_code) as char(2))
      end as assy_wh
    , case    when cast(    (select product_code 
                        from relationship_table 
                        where component_whouse=stock.warehouse 
                        and component_code=stock.product
                        and assembly_warehouse=relationship_union.assembly_warehouse 
                        and product_code=relationship_union.product_code) as char(20)) IS NULL then 
                                                                                    cast(    (select product_code 
                                                                                            from relationship_table 
                                                                                            where component_whouse=relationship_union.assembly_warehouse 
                                                                                            and component_code=relationship_union.product_code
                                                                                            and assembly_warehouse=relationship_run.assy_wh1
                                                                                            and product_code=relationship_run.assy_pr1) as char(20))
            else cast(    (select product_code 
                        from relationship_table 
                        where component_whouse=stock.warehouse 
                        and component_code=stock.product
                        and assembly_warehouse=relationship_union.assembly_warehouse 
                        and product_code=relationship_union.product_code) as char(20))
      end as assy_pr



, case    when relationship_run.stk_class LIKE 'TT%' then relationship_run.level else relationship_run.level + 1 end as [level]
, CAST(relationship_run.matpath + '->' + RTRIM(stock.warehouse) + RTRIM(stock.product) AS NVARCHAR(MAX)) AS [matpath]
FROM stock
inner join relationship_union 
on stock.warehouse=relationship_union.component_whouse
and stock.product=relationship_union.component_code
inner join relationship_run
on relationship_union.assembly_warehouse=relationship_run.component_warehouse
and relationship_union.product_code=relationship_run.component_code
)
SELECT 
assembly_warehouse, assembly_code, usage_quantity, component_warehouse, component_code, stk_class, kind
, assy_wh as parent_assy_wh, assy_pr as parent_assy_prod, level, matpath
FROM relationship_run
WHERE 
stk_class NOT LIKE 'TT%' 



option (maxrecursion 200)

Вышеупомянутый запрос работает, и я вполне доволен (я уверен, что некоторые найдут проблемы с этим :)). Проблема в том, что есть некоторые ошибочные данные, которые приводят к превращению go в бесконечное l oop, следовательно, в конце строки maxrecursion 200.

Проблема, вызывающая это, заключается в том, что в CTE Relationship_union мы получим такие элементы, как это:

AL A000000003   AE A000000003                  
AE A000000003   AL A000000003     

Вышеуказанное вызывает l oop, поскольку первый элемент имеет второй элемент как child, а второй элемент имеет первый элемент как дочерний. В этом CTE Relationship_union мне нужно выполнить запрос, который найдет мне все элементы с таким типом l oop, но я не совсем уверен, как их найти. Также возможно, что l oop может появиться на более низком уровне, например, элемент A состоит из элементов B C D, а элемент D - из элемента A - это приведет к al oop и, следовательно, I ' d необходимо выяснить это и удалить / скорректировать данные, чтобы элемент D больше не ссылался на своего старшего родителя как на дочерний.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...