2016-11-13 6 views
1

人は私が望むものが誤解されているように私の質問を編集しました。SQLを使用してそのような結果を生成する方法

私は、次の列を持つテーブルを持っている:

  1. 会社
  2. トランザクションID
  3. 取引日

は私が望む結果は次のとおりです。

 
|  COMPANY  | Transaction ID |Transaction Date |  GROUP 
|---------------------|------------------|------------------|---------- 
|  Company A  |  t_0001  | 01-01-2014 |   1 
|  Company A  |  t_0002  | 02-01-2014 |   1 
|  Company A  |  t_0003  | 04-01-2014 |   1 
|  Company A  |  t_0003  | 10-01-2014 |   2 
|  Company B  |  t_0004  | 02-01-2014 |   1 
|  Company B  |  t_0005  | 02-01-2014 |   1 
|  Company C  |  t_0006  | 03-01-2014 |   1 
|  Company C  |  t_0007  | 05-01-2014 |   2 

どこの取引日付は第一に企業のグループです。会社内の取引は、最も早いものから最新のものにソートされます。以前のトランザクションが3日以内に移動ウィンドウ期間内に実行された場合、トランザクションは行ごとにチェックされます。

たとえば、t_0002とt_0001が3日以内に離れているため、グループ1になります。t_0003とt_0002は3日以上離れているため、t_0003とt_0003は3日以上離れていてもグループ1になります。

私はこれをやり遂げる方法を考え出しました。最初に企業ごとにデータをグループ化して、トランザクションを日付順にソートしていますが、後になってしまいました。どのようなメソッドがありますか、私はこの結果を生み出すために使うことができますか?これに関する助言?

P.S.私はSQL Server 2014を使用しています。

+0

*日付の差異が3日未満の場合、トランザクションは同じグループに属するとみなされます*。あなたのグループは定義が悪いです!毎日取引がある場合はどうなりますか? – lovasoa

+0

これは_gapsとislands_の問題のようなものです。あなたはそれで検索することによって多くの例を見つけるでしょう。 –

+0

これについての回答はありませんか? – Winston

答えて

0

トランザクションIDごとに、各会社の日数の差異を決定しました。したがって、日差が3未満であればグループ1になります。その他は2です。要件に基づいて、遅延句を変更して使用します。

select *,isnull(
    case when datediff(day, 
    lag([Transaction Date]) over(partition by company order by [transaction id]),[Transaction Date])>=2 
    then 
    2 
    end ,1)group1 
    from #Table1 
+0

潜在的に無制限の数のグループがありますので、これはうまく動作しません – Winston

0

あなたは、グループの番号を気に連続番号がグループのために必要とされる場合

select *, 
dense_rank() over(partition by company order by transaction_date) - 
(select count(distinct transaction_date) from t 
where t1.company=company 
and datediff(dd,transaction_date,t1.transaction_date) between 1 and 2) grp 
from t t1 
order by 1,3 

Sample Demo

を使用し、

select company,transaction_id,transaction_date, 
dense_rank() over(partition by company order by grp) grp 
from (select *, dense_rank() over(partition by company order by transaction_date) - 
     (select count(distinct transaction_date) from t 
     where t1.company=company 
     and datediff(dd,transaction_date,t1.transaction_date) between 1 and 2) grp 
     from t t1 
     ) x 
order by 1,3 
+0

こんにちは、これはどのように動作するのですか? – Winston

+0

@Winston ..クエリーでは、説明したとおりの正確な結果が得られます。これはあなたが必要としているものではないと思いますか? –

+0

このデータセットを使用してみてください:http://rextester.com/SVUE71114最初の3つの行は、t002がt001から3日未満であるため、またt003がt002から3日未満離れているため、同じグループに属しているはずです。基本的には、前回の取引日ではなく、前回の取引日と常に比較されます。 – Winston

0
create table xn (
    [Company] char(1), 
    [Transaction ID] char(6), 
    [Transaction Date] date, 
    primary key ([Company], [Transaction ID], [Transaction Date]) 
); 

insert into xn values 
('A', 't_0001', '2014-01-01'), 
('A', 't_0002', '2014-01-02'), 
('A', 't_0003', '2014-01-04'), 
('A', 't_0003', '2014-01-10'), 
('B', 't_0004', '2014-01-02'), 
('B', 't_0005', '2014-01-02'), 
('C', 't_0006', '2014-01-03'), 
('C', 't_0007', '2014-01-05'); 
を使用しない場合

各クエリは以前のものをベースにしています。このようなクエリを書くためのより簡潔な方法がありますが、lag(...) over (...)のようなウィンドウ関数を学習するときには、この方法が役立つと思います。

ここで最初の取引日は、前の取引日を「現在の」行に戻します。

select 
    [Company], 
    [Transaction ID], 
    [Transaction Date], 
    lag ([Transaction Date]) over (partition by [Company] order by [Transaction Date]) as [Prev Transaction Date] 
from xn 

このクエリは、「現在の」取引日から前の取引日までの日数を決定します。

select 
    [Company], 
    [Transaction ID], 
    [Transaction Date], 
    [Prev Transaction Date], 
    DateDiff(d, [Prev Transaction Date], [Transaction Date]) as [Days Between] 
from (select 
      [Company], 
      [Transaction ID], 
      [Transaction Date], 
      lag ([Transaction Date]) over (partition by [Company] order by [Transaction Date]) as [Prev Transaction Date] 
     from xn) x 

これは、日数に基づいてグループ化します。

select 
    [Company], 
    [Transaction ID], 
    [Transaction Date], 
    case when [Days Between] between 0 and 3 then 1 
     when [Days Between] is null then 1 
     when [Days Between] > 3 then 2 
     else 'Ummm' 
    end as [Group Num] 
from (
     select 
      [Company], 
      [Transaction ID], 
      [Transaction Date], 
      [Prev Transaction Date], 
      DateDiff(d, [Prev Transaction Date], [Transaction Date]) as [Days Between] 
     from (select 
        [Company], 
        [Transaction ID], 
        [Transaction Date], 
        lag ([Transaction Date]) over (partition by [Company] order by [Transaction Date]) as [Prev Transaction Date] 
       from xn) x 
) y; 
関連する問題