SQL Сервер: развернуть вид с CTE - PullRequest
0 голосов
/ 16 июня 2020

У меня есть набор данных, как показано ниже:

ProductionOrder RootID  SalesOrder  Line    Quantity
829602  60124786_7275   60124786    7375    1
829603  60124786_7275   60124786    7400    1
109051  60126867_10000  60126867    10000   3
109058  60126867_10000  60126867    10050   3
109063  60126867_10000  60126867    10075   3
109071  60126867_10000  60126867    10125   3
109076  60126867_10000  60126867    10150   3

Мне было интересно, можно ли «разложить» это представление на отдельные компоненты для каждого количества. Например, последняя строка (ProductionOrder: 109076) вместо этого будет выглядеть следующим образом:

ProductionOrder RootID  SalesOrder  Line    QtyID
109076  60126867_10000  60126867    10150   1 of 3
109076  60126867_10000  60126867    10150   2 of 3
109076  60126867_10000  60126867    10150   3 of 3

И это будет сделано для каждой строки, динамика c на основе этого общего количества. Я могу добиться этого с помощью al oop, но это тысячи и тысячи строк, поэтому мне было интересно, может ли кто-нибудь помочь мне с примером этого на основе CTE. Я пытаюсь осознать это, но оказалось, что это сложно. Есть идеи?

Ответы [ 2 ]

0 голосов
/ 16 июня 2020

Этого очень легко добиться с помощью счетчика Tally. Если у вас очень маленькие значения, то работает JOIN к небольшому предложению VALUES:

--Sample data
WITH YourTable AS(
    SELECT *
    FROM (VALUES(829602,'60124786_7275',60124786,7375,1),
                (829603,'60124786_7275',60124786,7400,1),
                (109051,'60126867_10000',60126867,10000,3),
                (109058,'60126867_10000',60126867,10050,3),
                (109063,'60126867_10000',60126867,10075,3),
                (109071,'60126867_10000',60126867,10125,3),
                (109076,'60126867_10000',60126867,10150,3))V(ProductionOrder,RootID,SalesOrder,Line,Quantity))
--Solution
SELECT ProductionOrder,
       RootID,
       SalesOrder,
       Line,
       CONCAT(V.I,' of ',YT.Quantity) AS QtyID
FROM YourTable YT
     JOIN (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))V(I) ON V.I <= YT.Quantity

Если, однако, у вас есть гораздо большие значения для Quantity, тогда большее количество будет необходимо:

--Sample data
WITH YourTable AS(
    SELECT *
    FROM (VALUES(829602,'60124786_7275',60124786,7375,1),
                (829603,'60124786_7275',60124786,7400,1),
                (109051,'60126867_10000',60126867,10000,3),
                (109058,'60126867_10000',60126867,10050,3),
                (109063,'60126867_10000',60126867,10075,3),
                (109071,'60126867_10000',60126867,10125,3),
                (109076,'60126867_10000',60126867,10150,101))V(ProductionOrder,RootID,SalesOrder,Line,Quantity)),
--Solution
N AS(
    SELECT N
    FROM(VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT TOP (SELECT MAX(Quantity) FROM YourTable)
           ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1, N N2, N N3) --1,000 rows, add more N's for more rows
SELECT ProductionOrder,
       RootID,
       SalesOrder,
       Line,
       CONCAT(T.I,' of ',YT.Quantity) AS QtyID
FROM YourTable YT
     JOIN Tally T ON T.I <= YT.Quantity
ORDER BY ProductionOrder,
         T.I;
0 голосов
/ 16 июня 2020

Это не выполнимый запрос, однако его должно быть достаточно, чтобы дать вам представление о том, как использовать рекурсию для репликации строк заданное количество раз.

;WITH Normalized AS
(
    SELECT *, RowNumber = ROW_NUMBER() OVER (ORDER BY (SELECT 0)) FROM YourData
)
,ReplicateAmount AS
 (
    SELECT  ProductionOrder , RootID, SalesOrder, Line,  Quantity
    FROM Normalized

    UNION ALL

    SELECT R.ProductionOrder , R.RootID, R.SalesOrder, R.Line, Quantity=(R.Quantity - 1)
    FROM ReplicateAmount R INNER JOIN Normalized N ON R.RowNumber = N.RowNumber
    WHERE R.Quantity > 1
) 
...