2016-04-11 12 views
2

最終目標は、新製品の調整済み1日量を計算することです。在庫切れのT-SQLクエリ

まず、商品が在庫切れのとき、それが私を殺していることを知る必要があります。

TransaDate ItemCode TransQty OnHandBefore OnHandAfter 
1/1/2016 xyz-125  -5    20    15 
1/4/2016 xyz-126  -4    15    11 
1/7/2016 xyz-127  -2    11    9 
1/8/2016 xyz-128  -6    9    3 
1/8/2016 xyz-129  -3    3    0 
1/13/2016 xyz-130  20    0    20 
1/13/2016 xyz-131  -4    20    16 
1/13/2016 xyz-132  -10    16    6 
1/18/2016 xyz-133  -6    6    0 
1/23/2016 xyz-134  5    0    5 
1/26/2016 xyz-135  -5    5    0 
1/28/2016 xyz-136  20    0    20 
1/28/2016 xyz-137  -4    20    16 

OnHandAfterが0の場合はいつでも、在庫が1日中在庫切れと考えています。理想的には、前回または後に0がある日は無視されます。これはどちらも部分的な販売であるためです。しかし、私のために重要な、そして難しい部分は、アイテムが在庫切れになった日です。私はまっすぐ参加することはできませんので、エントリがありません。したがって、上記の例では、27日は掲載されていませんが、アイテムは26日と27日に在庫切れです。合計でこの例では1月8,9,10,11,12,13が在庫切れと表示され、その後20日が在庫になり、1月18,19,20,21,22,23,26,27,28も表示されます在庫切れ。毎日のボリューム調整15
:在庫切れの31分の49 = 1.58
日:

販売合計:49
一日平均出来高49 /(31-15)を= 3.06

無いので、レコードは売上がない日に作られています。範囲内のすべての日付を含む派生テーブル(またはそのようなもの)を作成する必要があると思います。より複雑にするには、各アイテムの日付範囲が動的になります。最初の30日間に販売されたアイテムの数がわかっている必要があります。したがって、開始日は各項目に対して動的である必要があります。

もう1つのメインテーブルはアイテムテーブルです。私はこれまでのことを示していますが、助けはまったく分かりません。私はこれを構造化する最善の方法について完全な犠牲を払っています。

これは私の最高のものですが、残念ながら不完全で残念な試みです。

With CTE_FirstSaleDate as 
(
SELECT MIN(TransDate) as FirstSoldOn FROM InventoryTransaction 
), 
WITH CTE_AllDatesTable 
AS 
(
    SELECT FirstSoldOn AS [date] 
    UNION ALL 
    SELECT DATEADD(dd, 1, [date]) 
    FROM CTE_DatesTable 
    WHERE DATEADD(dd, 1, [date]) < DATEADD(dd, 30, FirstSoldOn) 
), 
CTE_OOS as 
(
SELECT TOP 1 i.ItemCode, it.TransactionDate 
FROM InventoryTransaction it 
WHERE (it.OnHandAfter = 0) 
ORDER BY it.TransactionDate DESC 
) 
Select i.ItemCode, DaysCount, DaysOOSCount, AvgDlyVol, AdjDlyVol 
From Items i 
Join InventoryTransaction... 

私はテーブルの束を得ることができる方法に関するすべてのヘルプ、一緒のテーブルとすべてのこの他のものではないダイナミックな日数を大幅に理解されるであろう。確かに1つの魔法のスクリプトがある場合は素晴らしいだろうが、これは1ヶ月に1回実行されるので、それを分解することは問題ありません。

+0

あなたは探していますかo在庫切れの実際の日付を取得するか、日数を取得するか? –

+0

数日だけ。部分的に調整された1日の量を計算するだけでなく、何かが在庫切れの時間を見ることもできます。この例のように、データを掘り下げて、それがほぼ50%の在庫切れになるまで、データはあまりにも悪くはありません。 – user3096720

+0

ItemCodeは各トランザクションの一意の識別子であり、順番に割り当てられていますか? – Turophile

答えて

0

在庫切れの日数を取得するには、これを試してみてください:

;WITH CTE 
AS 
(
    SELECT *, ROW_NUMBER() OVER (ORDER BY TransaDate) as RN 
    FROM InventoryTransaction 
) 
SELECT c1.TransaDate, c2.TransaDate, DATEDIFF(d, c1.TransaDate, c2.TransaDate) As NumDays 
FROM CTE C1 
INNER JOIN CTE C2 
    ON C1.RN = C2.RN - 1 
WHERE C1.OnHandAfter = 0 AND C2.OnHAndBefore = 0 

EDIT

私はItemCodeは(特定のアイテムのすべてのトランザクションを結ぶ事列であることを前提とした場合これはあなたのサンプルから正しく見えません)、これはうまくいくでしょう:

;WITH CTE 
AS 
(
    SELECT * 
      ,ROW_NUMBER() OVER (Partition By ItemCode ORDER BY TransaDate) as RN 
    FROM InventoryTransaction 
) 
SELECT c1.TransaDate, c2.TransaDate, 
     DATEDIFF(d, c1.TransaDate, COALESCE(c2.TransaDate, c1.TransaDate)) As NumDays 
FROM CTE C1 
LEFT JOIN CTE C2 
    ON C1.RN = C2.RN - 1 AND C1.ItemCode = C2.ItemCode 
WHERE C1.OnHandAfter = 0 AND C2.OnHAndBefore = 0 
+0

これは動作しています。私はいくつかの日付範囲と異なる項目をテストしており、唯一の問題は、項目が日付範囲の終わりに在庫切れになった場合です。たとえば、私の日付範囲が03/01 - 03/31で、アイテムが03/30に在庫切れになった場合、結果はc1.TransDate = 2016-03-30、c2.TransDate = 2013-07-17およびNumDays = -987。 2013-07-17が次に行を見つけた方法がわかりません。おそらくNumDaysが<0でEndDate - C2.TransDateなら単純なIFを行うことができます。 – user3096720

+0

@ user3096720あなたの質問にデータを追加して、この問題を示すことができれば助かります。 2つ以上のアイテムがある場合は、これにも結合が必要です。アイテムコードがアイテムを識別していないため、サンプルデータから結合を使用する必要があります。 –

+0

ルールを提供した2番目のバージョン!私は本当にこの1つを勉強しなければなりません、自己結合されたパーティション化されたCTEは、私が視覚化または理解することは容易ではありませんが、結果に基づいてより多くの人々と協力する必要があります。あなたが提供した最初のバージョンは動作しましたが、実行には約2分かかりました。 2番目のバージョンは1秒未満で実行されました。素晴らしい!私はそれがパーティション分割であると仮定します。ありがとう、スティーブ、私に遊ぶためのこの新しい、光沢のある教育用おもちゃに感謝します。私は誠実に今のぞき見です! – user3096720

関連する問題