2016-05-03 22 views
-2

以下のようなデータ構造を持つ場合、カテゴリ別に製品の総数がカウントされ、日付がカウントされます。すべての値の差。TSQL - 日付の範囲の違いを計算する

たとえば、ストアABCでのThing1の違いは-4になります。しかし、私の実際のデータにはこれらの2つ以上の日付があります。だから私は、製品のすべての日付と四半期ごとのようなより広い範囲の違いを計算する必要があります。違いにより、日付に基づいて、最初と最後の合計の違いを意味し、1つの方法は、row_number()と条件付きの集約を使用している場合これは、SQL Server 2014

Store | Product | Total | Date  | 
ABC | Thing1 | 6  | 1-1-2013 | 
ABC | Thing2 | 2  | 1-1-2013 | 
XYZ | Thing1 | 4  | 1-1-2013 | 
XYZ | Thing2 | 7  | 1-1-2013 | 
ABC | Thing1 | 2  | 5-1-2013 | 
ABC | Thing2 | 4  | 5-1-2013 | 
XYZ | Thing1 | 3  | 5-1-2013 | 
XYZ | Thing2 | 9  | 5-1-2013 | 
+1

それはあなたが使用しているSQL Serverのバージョンを伝えるために、常に良いです。タグを使用する方が良い – FLICKER

+1

* ...店ABCでのThing1の違いは-4 * ...違いは何ですか? –

+0

質問を改善するためのヒントについては、[こちら](http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/)をお読みください。 – HABO

答えて

0

を使用している:

select store, product, 
     max(case when seqnum_asc = 1 then total end) as first_total 
     max(case when seqnum_desc = 1 then total end) as last_total, 
     (max(case when seqnum_desc = 1 then total end) - 
     max(case when seqnum_asc = 1 then total end) 
     ) as diff  
from (select t.*, 
      row_number() over (partition by store, product order by date) as seqnum_asc, 
      row_number() over (partition by store, product order by date desc) as seqnum_desc 
     from t 
    ) t 
where seqnum_asc = 1 or seqnum_desc = 1 
group by store, product; 
1

あなたを想定しています

;with cte as (
    select * 
    , LEAD(Total) over (partition by Store, Product order by Store, Product, Dt) NextTotal 
    from #t 
) 
select Store, Product, Dt, (NextTotal - Total) as Delta 
from cte 
where (NextTotal - Total) is not null 
order by Dt, Store, Product 

テストそれ:SQL 2012年以降、あなたは下のクエリを使用することができます

create table #t (Store varchar(10), Product varchar(10), Total int, Dt date) 

insert into #t values 
('ABC', 'Thing1', 6, '1-1-2013'), 
('ABC', 'Thing2', 2, '1-1-2013'), 
('XYZ', 'Thing1', 4, '1-1-2013'), 
('XYZ', 'Thing2', 7, '1-1-2013'), 
('ABC', 'Thing1', 2, '5-1-2013'), 
('ABC', 'Thing2', 4, '5-1-2013'), 
('XYZ', 'Thing1', 3, '5-1-2013'), 
('XYZ', 'Thing2', 9, '5-1-2013') 

結果:

╔═══════╦═════════╦════════════╦═══════╗ 
║ Store ║ Product ║  Dt  ║ Delta ║ 
╠═══════╬═════════╬════════════╬═══════╣ 
║ ABC ║ Thing1 ║ 2013-01-01 ║ -4 ║ 
║ ABC ║ Thing2 ║ 2013-01-01 ║  2 ║ 
║ XYZ ║ Thing1 ║ 2013-01-01 ║ -1 ║ 
║ XYZ ║ Thing2 ║ 2013-01-01 ║  2 ║ 
╚═══════╩═════════╩════════════╩═══════╝ 

てください "回答としてマーク" のポストは質問に答えた場合

+0

順番にパーティションを繰り返す目的はありません – Paparazzi

+0

ヒントありがとうございます。 – FLICKER

1

あなたは(SQL Server 2012のを持っていない場合としたがって、LEAD関数)これはあなたのために働くでしょう。

create table #Inventory 
(
    Store varchar(10), 
    Product  varchar(10), 
    Total  int, 
    DateCounted Date 
) 

insert into #Inventory values ('ABC', 'Thing1', 6, '2013-01-01') 
insert into #Inventory values ('ABC', 'Thing2', 2, '2013-01-01') 
insert into #Inventory values ('XYZ', 'Thing1', 4, '2013-01-01') 
insert into #Inventory values ('XYZ', 'Thing2', 7, '2013-01-01') 
insert into #Inventory values ('ABC', 'Thing1', 2, '2013-05-01') 
insert into #Inventory values ('ABC', 'Thing2', 4, '2013-05-01') 
insert into #Inventory values ('XYZ', 'Thing1', 3, '2013-05-01') 
insert into #Inventory values ('XYZ', 'Thing2', 9, '2013-05-01') 

; 
with #InventoryChange as 
(
    select rownum = row_number() over 
    (
     partition by Store, Product 
     order by Store, Product, DateCounted 
    ), Store, Product, Total, DateCounted 
    from #Inventory 
) 

select a.*, b.Total - a.Total as Difference 
from #InventoryChange a 
left join #InventoryChange b on a.Store = b.Store and a.Product = b.Product and a.rownum = b.rownum - 1 

このテクニックは、hereです。

0
WITH TEMP (Store , Product , Total , DT) 
AS (
SELECT 'ABC' , 'Thing1' , 6  , '1-1-2013' from dual union all 
SELECT 'ABC' , 'Thing2' , 2  , '1-1-2013' from dual union all 
SELECT 'XYZ' , 'Thing1' , 4  , '1-1-2013' from dual union all 
SELECT 'XYZ' , 'Thing2' , 7  , '1-1-2013' from dual union all 
SELECT 'ABC' , 'Thing1' , 2  , '5-1-2013' from dual union all 
SELECT 'ABC' , 'Thing2' , 4  , '5-1-2013' from dual union all 
SELECT 'XYZ' , 'Thing1' , 3  , '5-1-2013' from dual union all 
SELECT 'XYZ' , 'Thing2' , 9  , '5-1-2013' from dual 
) 

select Store, Product, max(DT), 
min(TOTAL) keep (dense_rank FIRST order by DT desc) - min(TOTAL) keep (dense_rank LAST order by DT desc) as DIFF 
from temp 
group by Store, Product 
; 

OUTPUT:

STORE PRODUCT MAX(DT)  DIFF 
----- ------- -------- ---------- 
ABC Thing1 5-1-2013   -4 
ABC Thing2 5-1-2013   2 
XYZ Thing1 5-1-2013   -1 
XYZ Thing2 5-1-2013   2