2016-09-09 2 views
1

버킷 채우기 쿼리 아래에 필자가 필러 테이블을 사용할 수 있도록 단일 필러 값을 사용하지 않기로했습니다. 샘플 데이터가 포함 된 쿼리를 참조하십시오. 필러 테이블과 재귀에 참여할 수 있기를 원하며 현재는 필러에서 단일 항목을 선택하고 있습니다.sql server 2008 CTE Bucket filling

이 문제를 완전히 이해하려면이 스레드를 살펴보십시오. http://www.sqlservercentral.com/Forums/Topic568498-338-1.aspx

고맙습니다.

SQL 2012 년
DECLARE @Buckets TABLE 
    (
     bucketID INT , 
     FullCapacity INT , 
     currentamount INT 
    ); 

DECLARE @Filler TABLE (ID INT, Filler INT); 

INSERT INTO @Buckets 
VALUES ('1', 85, 0) , 
     ('2', 80, 0) , 
     ('3', 75, 0) , 
     ('4', 70, 0) , 
     ('5', 50, 0) , 
     ('6', 40, 0); 

INSERT INTO @Filler 
VALUES ('1', 90) , 
     ('2', 40) , 
     ('3', 70) , 
     ('4', 50) , 
     ('5', 40) , 
     ('6', 30) , 
     ('7', 35); 

DECLARE @AmountToAllocate INT = (SELECT TOP 1 
              Filler 
            FROM  @Filler 
           ); 
--single filler amount 
;WITH Calculator 
      AS (SELECT bucketID , 
         FullCapacity , 
         currentamount , 
         AmountLeftToAllocate = CASE WHEN @AmountToAllocate > (FullCapacity 
                   - currentamount) 
                THEN @AmountToAllocate 
                  - (FullCapacity 
                   - currentamount) 
                WHEN @AmountToAllocate < 0 
                  AND ABS(@AmountToAllocate) > currentamount 
                THEN currentamount 
                  + @AmountToAllocate 
                ELSE 0 
               END , 
         NewAmount = CASE WHEN @AmountToAllocate > (FullCapacity 
                   - currentamount) 
              THEN FullCapacity 
              WHEN @AmountToAllocate < 0 
               AND ABS(@AmountToAllocate) > currentamount 
              THEN 0 
              ELSE currentamount 
               + @AmountToAllocate 
            END 
       FROM  @Buckets 
       WHERE bucketID = 1 
       UNION ALL 
       SELECT tr.bucketID , 
         tr.FullCapacity , 
         tr.currentamount , 
         AmountLeftToAllocate = CASE WHEN lr.AmountLeftToAllocate > (tr.FullCapacity 
                   - tr.currentamount) 
                THEN lr.AmountLeftToAllocate 
                  - (tr.FullCapacity 
                   - tr.currentamount) 
                WHEN lr.AmountLeftToAllocate < 0 
                  AND ABS(lr.AmountLeftToAllocate) > tr.currentamount 
                THEN tr.currentamount 
                  + lr.AmountLeftToAllocate 
                ELSE 0 
               END , 
         NewAmount = CASE WHEN lr.AmountLeftToAllocate > (tr.FullCapacity 
                   - tr.currentamount) 
              THEN tr.FullCapacity 
              WHEN lr.AmountLeftToAllocate < 0 
               AND ABS(lr.AmountLeftToAllocate) > tr.currentamount 
              THEN 0 
              ELSE tr.currentamount 
               + lr.AmountLeftToAllocate 
            END 
       FROM  @Buckets tr 
         INNER JOIN Calculator lr ON lr.bucketID + 1 = tr.bucketID 
      ) 
    SELECT bucketID , 
      FullCapacity , 
      Amount = NewAmount , 
      OldAmount = currentamount 
    FROM Calculator; 

답변

0

,하지만 여전히 SQL에서 해결책을 찾기 위해 노력하고 2008 년

DROP TABLE #Buckets 
CREATE TABLE #Buckets (bucketID INT, FullCapacity INT, CurrentAmount INT); 
INSERT INTO #Buckets 
VALUES ('1', 85, 0) , 
     ('2', 80, 0) , 
     ('3', 75, 0) , 
     ('4', 70, 0) , 
     ('5', 50, 0) , 
     ('6', 40, 0); 

DROP TABLE #Filler 
CREATE TABLE #Filler (FillerID INT, Filler INT); 
INSERT INTO #Filler 
VALUES ('1', 90) , 
     ('2', 40) , 
     ('3', 70) , 
     ('4', 50) , 
     ('5', 40) , 
     ('6', 30) , 
     ('7', 35); 

WITH ProcessedDebits AS ( 
    SELECT bucketID, FullCapacity, [from] = ([to] - FullCapacity), [to] 
    FROM (SELECT *, [to] = SUM(FullCapacity) OVER (PARTITION BY 1 ORDER BY bucketID 
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM #Buckets) d 
), 
ProcessedCredits AS ( 
    SELECT FillerID, Filler, [from] = ([to] - Filler), [to] 
    FROM (SELECT *, [to] = SUM(Filler) OVER (PARTITION BY 1 ORDER BY FillerID 
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM #Filler) d 
) 

SELECT 
    bucketID, FullCapacity, 
    DebitBalance = CASE 
     WHEN dr.[to] >= cr.[to] THEN (dr.[to] - cr.[to]) 
     WHEN dr.[to] < cr.[to] THEN 0 
     ELSE dr.[to] - MAX(cr.[to]) OVER(PARTITION BY 1 ORDER BY dr.bucketID 
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
      END, 
    FillerID, Filler, 
    CreditBalance = CASE 
     WHEN cr.[to] >= dr.[to] THEN (cr.[to] - dr.[to]) 
     WHEN cr.[to] < dr.[to] THEN 0 
     ELSE cr.[to] - MAX(dr.[to]) OVER(PARTITION BY 1 ORDER BY cr.FillerID 
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
      END 
FROM ProcessedDebits dr 
FULL OUTER JOIN ProcessedCredits cr 
    ON cr.[from] < dr.[to] 
    AND cr.[to] > dr.[from] 
ORDER BY bucketID, FillerID 
OPTION (MAXDOP 1);