SQL Server: перестановки / комбинации без зацикливания - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть два набора данных.Первый - это таблица рецептов продуктов вместе с продуктами, которые составляют рецепт.Второй набор данных содержит индивидуальные цены по продуктам (у меня может быть несколько цен для одного продукта).

Я пытаюсь добиться того, чтобы вывести набор результатов, содержащий уникальные перестановки для каждого из моих продуктоврецепты.Только выходные рецепты, в которых ВСЕ компоненты имеют цены во втором наборе данных, должны быть в выводе.

Предположение: один рецепт может иметь до 5 настроенных компонентов (не более).

DECLARE @ProductRecipe TABLE (ProductRecipeID INT, ComponentProductID INT)

INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) 
VALUES (21, 130), (21, 468), (21, 500), 
       (22, 468), (22, 500), 
       (23, 130), (23, 501)

DECLARE @ComponentPricing TABLE (PricingID INT, ProductID INT)

INSERT INTO @ComponentPricing (PricingID, ProductID)
VALUES (314023, 130), (313616, 130), (313071, 130),
       (312865, 130), (316323, 468), (316329, 468), (398864, 500)

Я бы хотел, чтобы мой вывод выглядел так:

Пример вывода

enter image description here

Я пробовал CTE и сам присоединяется, но ядаже не могу приблизиться к желаемому выводу ..: (

Я использую SQL Server 2012

1 Ответ

0 голосов
/ 22 декабря 2018

Я предполагаю, что вы работаете с SQL Server 2008 или новее, что необходимо для работы функции dense_rank().

Решение, приведенное ниже, проходит через несколько шагов, изложенных в комментариях.Один из вызовов заключается в том, что я изменил одну из @ProductRecipe записей с (22, 130) на (22, 468), так как считаю, что это предполагаемые данные выборки, поскольку Component1 требуемого вывода включает в себя PricingID значения 316323 и 316329.

Ответ:

DECLARE @ProductRecipe TABLE (ProductRecipeID INT, ComponentProductID INT)
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (21, 130)
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (21, 468)
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (21, 500)
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (22, 468) --values were (22, 130) in question
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (22, 500)
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (23, 130)
INSERT INTO @ProductRecipe (ProductRecipeID, ComponentProductID) VALUES (23, 501)

DECLARE @ComponentPricing TABLE (PricingID INT, ProductID INT)
INSERT INTO @ComponentPricing (PricingID, ProductID)
VALUES (314023, 130)
 , (313616, 130)
 , (313071, 130)
 , (312865, 130)
 , (316323, 468)
 , (316329, 468)
 , (398864, 500)

; with base as
    (
        --Joining the two datasets together.
        select pr.ProductRecipeID
        , pr.ComponentProductID
        , cp.PricingID
        from @ProductRecipe as pr
        left join @ComponentPricing as cp on pr.ComponentProductID = cp.ProductID   
    )
    , pr_exclude as
    (
        --Identifying that ProductRecipeID 23 should be excluded because of the 501 NULL value
        select distinct b.ProductRecipeID
        from base as b
        where b.PricingID is null   
    )
    , final_base as
    (
        --Assigning Rank to each ComponentProductID
        select b.ProductRecipeID
        , b.ComponentProductID
        , b.PricingID
        , dense_rank() over (partition by b.ProductRecipeID order by b.ComponentProductID asc) as prod_rnk
        from base as b
        left join pr_exclude as p on b.ProductRecipeID = p.ProductRecipeID
        where 1=1
        and p.ProductRecipeID is null
    )
--Joining it all together
select a.ProductRecipeID
, a.PricingID as Component1
, b.PricingID as Component2
, c.PricingID as Component3
, d.PricingID as Component4
, e.PricingID as Component5
from final_base as a
left join final_base as b on a.ProductRecipeID = b.ProductRecipeID and b.prod_rnk = 2
left join final_base as c on b.ProductRecipeID = c.ProductRecipeID and c.prod_rnk = 3
left join final_base as d on c.ProductRecipeID = d.ProductRecipeID and d.prod_rnk = 4
left join final_base as e on d.ProductRecipeID = e.ProductRecipeID and e.prod_rnk = 5
where a.prod_rnk = 1
order by 1, 2, 3, 4, 5, 6
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...