2017-02-23 24 views
3

私はこのようなデータテーブルを持っています。SQLパーティション行のグループを交互に変更することによって

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

変換線は、量がどこに行き、消費量がどのくらいの量を使用しているかを教えてくれます。消費ラインは、前のLotIdまでのそのLotIdのすべての前の変換ラインに適用されるか、前の変換&が同じLotIdである場合、グループ化を消費する。さらに、レンチを1つ追加すると、グループ内の変換および消費線の数が変化します。私が働いていることの一つは、変換ラインが最初に来て、消費した次回に新しいグループが始まったことを知っていることです。

|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 

(この例の目的のために、我々は数量がすべての当事者間で均等に分割されていることだけを前提とします)

  • グループA1グループB1
  • フー&バーの間に100分割がありましたボブとフレッドの間に125のスプリットがあった
  • グループB2サリーの間で60スプリットがあった&フレッド
  • グループC1スプリットされた25 SQL RANK()DENSE_RANK()、私は私にこのグループを与えるクエリを仕事にしようとしています& ROW_NUMBER()ウィンドウを使用してトゥイーンバーとフレッド

。このグループ分けができたら、データを自分自身に戻して、最終的に私の目的地のどれがどれくらい受け取ったかを決定することができます。

これはSQL2008上です。

+0

順序を適用するために使用されうる重要なシーケンシャル値はありますか? – scsimon

+0

はい、キーはauto_identです。ここでは、簡単にできるので、順番にすべてを入れています。しかし、レコードをテーブルに挿入する順序を取得するために、そのキー値によって順序付けすることができます。 –

+0

データ内の何がB1からB2への変化を示していますか? –

答えて

2

common table expressionouter apply()、そして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

このクエリはテストされていません。 –

関連する問題