2012-10-24 3 views
3

У меня есть таблица, которая отслеживает взаимодействие пользователя с записью клиента. Я хочу отслеживать продолжительность каждого «касания» пользователем, то есть количество времени, затрачиваемого каждым пользователем, каждый раз, когда нам требуется доступ к записи клиента. У меня есть основы, используя ROW_NUMBER() OVER (PARTITION BY | ORDER BY). Проблема, из-за которой я не могу раздобыть мозг гороха, заключается в том, как разделить два разных пользовательских касания, когда эти штрихи являются последовательными, но разделяются значительным количеством времени. Я не знаю, что я объяснил, что ясно, но приведенные ниже примеры следует уточнить:t-sql последовательная продолжительность

Ниже приведен пример данных, которые я могу запросить успешно:

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 

Проблема возникает тогда, когда «значительное» количество времени проходит между концом первого прикосновения и начало второго прикосновения (ради аргумента, если час проходит между касаниями, это разные штрихи).

Нужный набор результатов из приведенных выше данных является

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 

Заранее спасибо за любую помощь вы можете предоставить. Я изучал острова и пробелы в попытке решить эту дилемму, но я до сих пор не могу понять это.

ответ

3

Пожалуйста, попробуйте это.SQL Fiddle

;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 

UPDATE: База на обновленной вопрос, пожалуйста, используйте следующий запрос

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 
+0

Спасибо , Это близко, но не совсем то, что я ищу. Вина моя, поскольку приведенные мною примеры не содержат достаточной информации. Этот запрос работает с примерами, которые были опубликованы, но не работает, если данные более подробные. Например, используя второй пример данных из моего исходного сообщения, измените время на последних четырех строках на 11:15:24, 11:26:38, 11:34:55 и 11:36:22. Теперь запустите этот запрос, и вы увидите, что он вычисляет разницу во времени между строками A и B, затем B и C, затем C и D ... – Kris

+0

@ Kris, каков ваш ожидаемый результат в этом случае? Не могли бы вы обновить свой вопрос? – EricZ

+0

Эрик. Я обновил вопрос вторым примером, как описано выше. В вашем удобстве, пожалуйста, просмотрите. Прошу прощения за задержку в ответе. – Kris

0

Не могли бы вы добавить и заполнить поле sessionID в своей таблице отчетов? то это может быть так же просто:

select  sessionId, datediff(second, min(time),max(time)) 
from  Trip_History_reporting 
group by sessionId 
+0

Я предпочел бы не создать столбец этой таблицы, чтобы разместить этот запрос. Я буду, если захочу, но это определенно не мое предпочтение. Сказав это, у меня по-прежнему осталась аналогичная проблема: если я добавлю рекомендуемое поле SessionID (которое было бы ручным манипулированием данными, а не созданным программным обеспечением), как его заполнить? – Kris

+0

@Kris Если вы не можете получить 'sessionId' из приложения, то вы можете создать триггер в таблице, чтобы проверить, имеет ли пользователь уже строку со значением времени в течение нескольких минут текущего времени – paul

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 
Смежные вопросы