У меня есть запрос, который проходит через уровни в рамках отношения продуктов и генерирует список всех продуктов, необходимых для производства продукта сверху вниз.
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 больше не ссылался на своего старшего родителя как на дочерний.