2016-07-20 8 views
4

ここでは、基本的なT-SQLユーザーです。私はタスクを完了しようとすると問題を抱えており、いくつかの指針に感謝します。英語が私の母国語ではないので、どんな誤りでも事前に謝罪します。取引日に基づいて顧客の旅行を計算する

私は多くのトランザクションを持つテーブルを持っていますが、簡単にするために、2つの列、つまり顧客のCUSTOMER_IDとトランザクションの日付のDATEしかないとしましょう。

私の顧客は、町にいる間にたくさんの取引をしますが、戻って再び取引を開始するまでに数週間、数ヶ月、または数年かかることがあります。私はどういうわけかそれらの "Trips"の各1つを特定し、関連するトランザクションをグループ化したいと思います。次に、旅行期間、取引回数などを計算するような細かい操作を行いたいと思います。

Trip新たな取引は、IDLE期間10日後に発生します。

私はより良いいくつかの簡単な例を使って、私の要求を説明してみましょう:

は、これが私の取引のテーブルです:

+-------------+------------+ 
| CUSTOMER_ID | DATE | 
+-------------+------------+ 
| JHON  | 01-01-2016 | 
| JHON  | 01-02-2016 | 
| PEDRO  | 01-02-2016 | 
| JHON  | 01-05-2016 | 
| MIKE  | 01-05-2016 | 
| MIKE  | 01-10-2016 | 
| JHON  | 01-07-2016 | 
| …   | …   | 
| JHON  | 02-15-2016 | 
| JHON  | 02-18-2016 | 
| MIKE  | 02-19-2016 | 
| MIKE  | 02-19-2016 | 
+-------------+------------+ 

は、これまでのところ私は、顧客の訪問を列挙するために、このクエリを作りました:

SELECT 
    CUSTOMER_ID, 
    DATE, 
    ROW_NUMBER() OVER(PARTITION BY CUSTOMER_ID ORDER BY DATE) as VISIT_NUM 

FROM 
    TRANSACTIONS 
WHERE 
    CUSTOMER_ID IN ('JHON','MIKE','PEDRO') 

そのクエリを実行すると、このような結果を与えるだろう

ここでは難しい部分があります。私は何とか前のステップとして上記のクエリを使用して質問を作成する必要があります。理想的な結果は次のようになります。

+-------------+----------+---------------+-------------+---------------+--------------+ 
| CUSTOMER_ID | TRIP_NUM | TRIP_START_DT | TRIP_END_DT | TRIP_DURATION | TRANSACTIONS | 
+-------------+----------+---------------+-------------+---------------+--------------+ 
| JHON  |  1 | 01-01-2016 | 01-07-2016 |    7 |   3 | 
| JHON  |  2 | 02-15-2016 | 02-18-2016 |    3 |   2 | 
| MIKE  |  1 | 01-05-2016 | 01-10-2016 |    5 |   2 | 
| MIKE  |  2 | 02-19-2016 | 02-19-2016 |    1 |   2 | 
| PEDRO  |  1 | 01-02-2016 | 01-02-2016 |    1 |   1 | 
+-------------+----------+---------------+-------------+---------------+--------------+ 

ご覧のとおり、ジョンさんは1月に3回、2月にもう一度戻ってきました。 1月の最後の取引から10日以上が経過したので、彼の新たな取引は新しい「旅行」であると考えてみたい。マイクも1月に何らかの活動をしていたし、2月にも戻ってきた。彼の2回目の旅行で同じ日に2回の取引をしたので、それも説明したい。顧客が1日しか来ておらず、何らかの活動(ペドロ氏の場合)があった場合、私は単日の単一取引レコードを旅行記録として考慮したいと思います。

これについては、私は非常に光栄に感謝するだろう、私は正直に進める方法については考えていない(私はカーソルについて読んできたが、この時点で暗い魔法のように思える、 )。

文法上の誤りや私の一部の可能性のある省略については、再度謝罪してください。私は必要に応じてさらに何かを明らかにするだろう。旅行期間の計算

+3

あなたの英語は、英語のネイティブスピーカーの99%よりも優れています。 –

答えて

1

私は他の場所で完璧な答えを見つけました。すべてのクレジットはRedditユーザーnvarscarに送られ、驚くべき解決策になります!

私は場合には他の誰かが将来的にそれを必要とし、以下の彼/彼女の答えを単にコピーします:

あなたは、現在の行の間 行を集約するのに役立ちますウィンドウ関数の機能を使用することができると前のすべてのもの。コードも長く のように見えますが、少なくとも実行された手順が表示されます。

DECLARE @t TABLE 
    ([CUSTOMER_ID] varchar(5), [DATE] datetime) 
; 

INSERT INTO @t 
    ([CUSTOMER_ID], [DATE]) 
VALUES 
    ('JHON', '2016-01-01 00:00:00'), 
    ('JHON', '2016-01-02 00:00:00'), 
    ('PEDRO', '2016-01-02 00:00:00'), 
    ('JHON', '2016-01-05 00:00:00'), 
    ('MIKE', '2016-01-05 00:00:00'), 
    ('MIKE', '2016-01-10 00:00:00'), 
    ('JHON', '2016-01-07 00:00:00'), 
    ('JHON', '2016-02-15 00:00:00'), 
    ('JHON', '2016-02-18 00:00:00'), 
    ('MIKE', '2016-02-19 00:00:00'), 
    ('MIKE', '2016-02-19 00:00:00'), 
    ('JHON', '2016-02-01 00:00:00'), 
    ('JHON', '2016-02-02 00:00:00'), 
    ('PEDRO', '2016-03-02 00:00:00'), 
    ('JHON', '2016-03-05 00:00:00'), 
    ('MIKE', '2016-05-05 00:00:00'), 
    ('MIKE', '2016-05-10 00:00:00'), 
    ('JHON', '2016-03-07 00:00:00'), 
    ('JHON', '2016-04-15 00:00:00'), 
    ('JHON', '2016-04-18 00:00:00'), 
    ('MIKE', '2016-06-19 00:00:00'), 
    ('MIKE', '2016-06-19 00:00:00') 
; 


WITH CTE1 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, COUNT(*) AS Transactions 
FROM @t 
GROUP BY 
    [CUSTOMER_ID] 
, [DATE] 
) 
, CTE2 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, Transactions 
, DATEDIFF(day,LAG([DATE]) OVER (PARTITION BY [CUSTOMER_ID] ORDER BY [DATE]),[DATE]) AS DaysSinceLastTransaction 
FROM CTE1 
) 
, CTE3 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, Transactions 
, CASE WHEN DaysSinceLastTransaction > 10 THEN 1 ELSE 0 END AS TripTag --Here we set the idle tag 
FROM CTE2 
) 
, CTE4 AS (
SELECT 
    [CUSTOMER_ID] 
, [DATE] 
, Transactions 
, SUM(TripTag) OVER (PARTITION BY [CUSTOMER_ID] ORDER BY [DATE] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS TripTag 
FROM CTE3 
) 
SELECT 
    [CUSTOMER_ID] 
, TripTag+1 AS TripNumber 
, MIN ([DATE]) AS TripStartDate 
, MAX ([DATE]) AS TripEndDate 
, DATEDIFF(day, MIN ([DATE]), MAX ([DATE])) AS TripDuration 
, SUM(Transactions) AS Transactions 
FROM CTE4 
GROUP BY [CUSTOMER_ID], TripTag 
2

はあなたの例では、全従業員のための標準ではありませんので、私はすべての

DEMO HERE

;with cte 
as 
(select cid,datee,datepart(month,datee) as monthh, 
    dense_rank() over (partition by cid order by datepart(month,datee)) as samemonth, 
count(0) over (partition by cid,datepart(month,datee)) as cnt 
from #temp 
) 
,cte1 as 
(
select cid,max(samemonth) as tripnumber,min(datee) as startdate,max(datee) as enddate, 
max(cnt) as numberoftrips 
from cte 
group by cid,samemonth 
) 
select *,datediff(day,startdate,dateadd(day,1,enddate))as duration 
from cte1 

出力のための最初の顧客IDを追跡するためにそれを微調整しています

cid tripnumber startdate  enddate numberoftransactions duration 
JHON 1  2016-01-01 2016-01-07 3     7 
JHON 2  2016-02-15 2016-02-18 2     4 
MIKE 1  2016-01-05 2016-01-10 2     6 
MIKE 2  2016-02-19 2016-02-19 2     1 
PEDRO 1  2016-01-02 2016-01-02 1     1 
+1

ありがとうございました。正確には私が欲しかったのではありませんでしたが、それは私を助けます – JorgeDS

関連する問題