3

顧客のレコードとのユーザー インタラクションを追跡するテーブルがあります。ユーザーによる各「タッチ」の継続時間、つまり、顧客の記録にアクセスする必要があるたびに、各ユーザーが費やした時間を追跡したいと考えています。ROW_NUMBER() OVER (PARTITION BY | ORDER BY) を使用して基本を理解しました。エンドウ豆の頭脳を理解できない問題は、2 つの異なるユーザー タッチが連続しているがかなりの時間間隔がある場合に、それらをどのように分離するかということです。それを明確に説明したかどうかはわかりませんが、以下の例で明確にする必要があります。

正常にクエリできるデータの例を次に示します。

DATE        TIME        USER
11/17/2011  1:30:47     ZDBatch
11/17/2011  1:32:40     ZDBatch
12/13/2011  10:39:46    EMSZC27
12/13/2011  10:45:48    EMSZC27

目的の結果セットは

DURATION (MIN)  USER
1.883   ZDBatch
6.033   EMSZC27

これは、次のクエリで実現されます (上記の例からいくつかの列を除外していることに注意してください)。

; WITH CTE1 AS
    (
    SELECT  ROW_NUMBER() OVER (PARTITION BY thr.[tdate], thr.[job], thr.[who], thr.[moddate]  ORDER BY thr.[moddate]) AS RowNo,
    thr.[tdate], thr.[job], thr.[moddate], thr.[modtime], thr.[seq], thr.[who], 
         thr.[description], thr.[histtype], thr.[attachment], thr.[data1], thr.[data2]
    FROM    Trip_History_Reporting thr
    WHERE   thr.[tdate] = '2011-10-24' --AND thr.[job] IN ('0653-A', '0128-A')
        AND LEFT(thr.[description], 8) <> 'Recalled'
        AND (LEFT(thr.[who],5) = 'EMSZC' OR thr.[who] = 'ZDBatch')
        --ORDER BY thr.[moddate], thr.[modtime]
    )

SELECT  tdate, job, MIN(RowNo), MAX(RowNo), MIN(modtime) AS [Start], MAX(modtime) AS [End], 
    CAST(CAST(DATEDIFF(SECOND, MIN(modtime), MAX(modtime)) AS DECIMAL(6,0))/60 AS DECIMAL(8,2)) AS [Duration (Min)], 
    who, moddate
FROM    CTE1
GROUP BY    tdate, job, who, moddate

正常にクエリできないデータの例を次に示します (同じユーザーによる連続した個別のタッチ)。

DATE           TIME     USER
11/1/2011       6:34:48 EMSZC34
11/1/2011       6:35:08 EMSZC34
11/1/2011       6:35:08 EMSZC34
11/1/2011       6:35:08 EMSZC34
11/1/2011       6:35:08 EMSZC34
11/1/2011       6:35:08 EMSZC34
11/15/2011      11:08:32    EMSZC34
11/15/2011      11:09:14    EMSZC34
11/15/2011      11:09:14    EMSZC34
11/15/2011      11:09:14    EMSZC34
11/15/2011      11:09:14    EMSZC34
11/15/2011      11:09:14    EMSZC34

この問題は、最初のタッチの終わりから 2 番目のタッチの開始までの間に「かなりの」時間が経過した場合に発生します (議論のために言うと、タッチの間に 1 時間経過した場合、それらは別個のタッチです)。

上記のデータからの望ましい結果セットは次のとおりです。

DURATION (MIN)      USER
     0.333          EMSZC34
     0.7             EMSZC34

これはとても簡単に思えますが、私には理解できません。私の厚かましさに対するアイデア、提案、あからさまな嘲笑を前もって感謝します。

返信が遅くなりましたことをお詫び申し上げます。私は、このグループが無料でサポートを提供していることを認識しており、すぐに返信しないことでそれを利用するつもりはありません。このようなことが二度と起こらないように最善を尽くします。

EricZ の要求に従って、目的の出力の例を次に示します。

DATE           TIME     USER
11/1/2011     6:34:48   EMSZC34
11/1/2011     6:35:08   EMSZC34
11/1/2011     6:35:08   EMSZC34
11/1/2011   6:35:08 EMSZC34
11/1/2011   6:35:08 EMSZC34
11/1/2011   6:35:08 EMSZC34
11/15/2011    11:08:32  EMSZC34
11/15/2011    11:09:14  EMSZC34
11/15/2011    11:09:14  EMSZC34
11/15/2011    11:15:24  EMSZC34
11/15/2011    11:26:38  EMSZC34
11/15/2011    11:34:55  EMSZC34
11/15/2011    11:36:22  EMSZC34

望ましい出力:

DURATION (MIN)  USER
0.333   EMSZC34
27.833  EMSZC34

どうぞよろしくお願いいたします。このジレンマを解決するために島とギャップを調査してきましたが、まだわかりません。

4

3 に答える 3

3

これを試してください。SQL フィドル

;WITH c1 AS (
SELECT  DISTINCT CAST(LEFT(CONVERT( VARCHAR(20),moddate,112),10)+ ' ' + modtime AS DATETIME)as moddate ,moduser
FROM    Trip_History_Reporting
)
, c2 AS (
SELECT moddate,moduser,ROW_NUMBER() OVER (PARTITION BY moduser ORDER BY moddate) as row_no
FROM c1
)
, c3 AS (
SELECT c.moddate as startdate, cc.moddate as enddate, DATEDIFF(SECOND,c.moddate,cc.moddate) as diff,c.moduser
FROM c2 c 
INNER JOIN c2   cc 
    ON c.moduser= cc.moduser
    AND c.row_no = cc.row_no -1 
)
SELECT  *,diff/60.00 as diff_in_min
FROM    c3
WHERE diff <= 60*60 -- an hour in second

更新: 更新された質問に基づいて、次のクエリを使用してください

WITH c1 AS (
SELECT  DISTINCT CAST(LEFT(CONVERT( VARCHAR(20),moddate,112),10)+ ' ' + modtime AS DATETIME)as moddate ,moduser
FROM    Trip_History_Reporting
)
, c2 AS (
SELECT moddate,moduser,(SELECT MAX(cc.moddate) FROM c1 cc WHERE cc.moddate <= DATEADD(hour,1,c.moddate) AND cc.moddate > c.moddate AND c.moduser = cc.moduser) AS endtime
FROM c1 c
)
, c3 AS (
SELECT  moduser, MIN(moddate) as [start],endtime AS [end]
FROM    c2
WHERE endtime IS NOT NULL
GROUP BY moduser,endtime
)
SELECT  *,DATEDIFF(SECOND,[start],[end])/60.0  as diff_in_min 
FROM  c3
于 2012-10-24T17:03:59.417 に答える
0

レポート テーブルに「sessionID」フィールドを追加して入力していただけないでしょうか。次に、次のように簡単にできます。

select     sessionId, datediff(second, min(time),max(time)) 
from       Trip_History_reporting 
group by   sessionId
于 2012-10-24T12:03:17.597 に答える
0

これは疑似 TSQL です。
構文が正しくありません。
すべての行を注文します。
RowNumber + 1 で結合します
。偶数のみを使用します。

WITH Ordered AS
(
    SELECT DATE, TIME, USER
    ROW_NUMBER() AS RowNumber
    FROM Trip_History_Reporting 
) 
select O1.USER, (O2.TIME - O1.TIME) 
from order O1 
join order O2 
on O2.RowNumber = O1.RowNumber + 1 
where O1%2 = 0
于 2012-10-24T13:31:53.203 に答える