2017-02-23 10 views
3

나는 이런 종류의 데이터 테이블을 가지고 있습니다.SQL 파티션 행 그룹을 번갈아 사용하여

변환 선은 수량이 어느 부분에 있는지 알려주고 소모 선은 사용량의 양을 알려줍니다. 소비 라인은 이전 LotId까지의 해당 LotId에 대한 모든 이전 변환 라인에 적용되거나 이전 Lot그룹화를 사용하는 LotId와 동일하다면 적용됩니다. 추가 된 렌치 하나를 던지려면 그룹 내의 변환 및 소비 행 수가 가변적입니다. 내가 나를 위해 일하는 한가지는 변환 라인이 먼저오고 소비 한 다음 번에 새로운 그룹화가 시작되었다는 것을 알게되면 변환 할 때입니다.

|Key|LotId|TransactionType|Quantity|Destination|Grouping 
|1 |A |Transform  |NULL |Foo  |A1 
|2 |A |Transform  |NULL |Bar  |A1 
|3 |A |Consume  |100  |NULL  |A1 
--------------------------------------------------------- 
|4 |B |Transform  |NULL |Bob  |B1 
|5 |B |Transform  |NULL |Fred  |B1 
|6 |B |Consume  |75  |NULL  |B1 
|7 |B |Consume  |50  |NULL  |B1 
--------------------------------------------------------- 
|8 |B |Transform  |NULL |Sally  |B2 
|9 |B |Transform  |NULL |Fred  |B2 
|10 |B |Consume  |60  |NULL  |B2 
--------------------------------------------------------- 
|11 |C |Transform  |NULL |Bar  |C1 
|12 |C |Transform  |NULL |Fred  |C1 
|13 |C |Consume  |25  |NULL  |C1 

는 푸 & 사이 100 분할 바
  • 그룹 B1

    • 그룹 A1이 있었다 (이 예제의 목적을 위해 우리는 단지 양이 모든 당사자에 걸쳐 균등 분할이라고 가정합니다) 밥과 프레드 사이에 125 스플릿이있었습니다
    • 그룹 B2 사이 샐리 & 프레드
    • 그룹 C1 25 스플릿 는 SQL RANK(), DENSE_RANK(), 나는 나에게이 그룹을 줄 것이다 쿼리를 해결하려고 노력하고 & ROW_NUMBER() 윈도우를 사용 트윈 바 프레드

    . 이 그룹을 만들 수있게되면 데이터를 다시 그 자리에 포함시켜 궁극적으로 목적지별로 얼마나 많은지를 결정할 수있게됩니다.

    이것은 SQL2008에 있습니다. common table expression, outer apply()의 조합을 사용하여

  • +0

    순서를 적용하는 데 사용할 수 있습니다 키 순차적 가치인가? – scsimon

    +0

    예 키가 auto_ident입니다. 여기서 나는 순차적으로 모든 것을 순차적으로 처리했다. 그러나 레코드를 테이블에 삽입하는 순서를 얻기 위해이 키 값으로 정렬 할 수 있습니다. –

    +0

    데이터에서 B1에서 B2 로의 변경을 나타내는 것은 무엇입니까? –

    답변

    2

    dense_rank()

    참고 : 나는 그래서 그것을 대괄호를 사용하지 않았을 tKey에 열 Key을 변경했습니다.

    ;with cte as (
        select * 
        , PrevTransactionType=isnull(x.Prev_TransactionType,'Consume') 
        from t 
        outer apply (
         select top 1 
         Prev_TransactionType = TransactionType 
         from t as i 
         where i.tKey < t.tKey 
         order by i.tKey desc 
        ) as x 
    ) 
    select t.tKey, t.LotId, t.TransactionType, t.Quantity, t.Destination 
    , Grouping = LotId + convert(varchar(10),dense_rank() over (
        partition by LotId 
        order by GroupNumber 
        ) 
    ) 
    from cte as t 
    outer apply (
        select top 1 
        GroupNumber = i.tKey 
        from cte as i 
        where i.tKey <= t.tKey 
         and i.TransactionType = 'Transform' 
         and i.PrevTransactionType = 'Consume' 
        order by i.tKey desc 
        ) x 
    

    테스트 설정 : http://rextester.com/LWV40248

    결과 :

    +------+-------+-----------------+----------+-------------+----------+ 
    | tKey | LotId | TransactionType | Quantity | Destination | Grouping | 
    +------+-------+-----------------+----------+-------------+----------+ 
    | 1 | A  | Transform  | NULL  | Foo   | A1  | 
    | 2 | A  | Transform  | NULL  | Bar   | A1  | 
    | 3 | A  | Consume   | 100  | NULL  | A1  | 
    | 4 | B  | Transform  | NULL  | Bob   | B1  | 
    | 5 | B  | Transform  | NULL  | Fred  | B1  | 
    | 6 | B  | Consume   | 75  | NULL  | B1  | 
    | 7 | B  | Consume   | 50  | NULL  | B1  | 
    | 8 | B  | Transform  | NULL  | Sally  | B2  | 
    | 9 | B  | Transform  | NULL  | Fred  | B2  | 
    | 10 | B  | Consume   | 60  | NULL  | B2  | 
    | 11 | C  | Transform  | NULL  | Bar   | C1  | 
    | 12 | C  | Transform  | NULL  | Fred  | C1  | 
    | 13 | C  | Consume   | 25  | NULL  | C1  | 
    +------+-------+-----------------+----------+-------------+----------+ 
    
    +0

    굉장한 대답, 나는 확인할 필요가있다. 그러나 나는 LAG가 2008 년에 가능하다고 생각하지 않는다. –

    +0

    @NASlacker 아야, 네 말이 맞아. 대신'apply()'를 써서 쓰겠습니다. - 지금 업데이트되었습니다. – SqlZim

    +0

    이 작품은 훌륭합니다! 감사! –

    1
    CREATE TABLE #KeyWithRowNum (
        Key INT NOT NULL 
         UNIQUE, 
        LotId INT NOT NULL, 
        RowNum INT NOT NULL, 
         PRIMARY KEY (RowNum, LotId), 
        TransactionType VARCHAR(50) NOT NULL -- Replace current data type and max. length 
    ) 
    SELECT j.Key, j.LotId, ROW_NUMBER() OVER(PARTITION BY j.LotId ORDER BY j.Key) AS RowNum, TransactionType 
    FROM dbo.CocoJambo j; 
    
    WITH CteRecursion 
    AS (
    SELECT crt.Key, crt.LotId, crt.RowNum, crt.TransactionType, 1 AS GroupId 
    FROM #KeyWithRowNum crt 
    WHERE RowNum = 1 
    UNION ALL 
    SELECT crt.Key, crt.LotId, crt.RowNum, crt.TransactionType, CASE WHEN crt.TransactionType = 'Transform' AND (prev.TransactionType = 'Consume' OR prev.TransactionType IS NULL) THEN prev.GroupId + 1 ELSE prev.GroupId END AS GroupId 
    FROM #KeyWithRowNum crt 
    INNER JOIN CteRecursion prev ON crt.LotId = prev.LotId AND crt.RowNum - 1 = prev.RowNum 
    ) 
    SELECT *, LotId + LTRIM(x.GroupId) AS Grouping 
    FROM CteRecursion x 
    -- OPTION(MAXRECURSION 32767) -- Default is 100 
    
    +0

    이 쿼리를 테스트하지 않았습니다. –