Задача TSQL для расчета различий между двумя датами внутри одной таблицы - PullRequest
3 голосов
/ 01 августа 2011

В MSSQL 2008 у меня есть таблица и данные, которые выглядят так

create table #tempData
(user_id int,type varchar(10),ts datetime)

insert into #tempData
select 1,'ENTER','2011-01-30 15:00:00'
union all
select 1,'EXIT','2011-01-31 16:00:00'
union all
select 1,'ENTER','2011-02-1 18:00:00'
union all
select 1,'EXIT','2011-02-10 21:00:00'
union all
select 2,'ENTER','2011-01-10 21:00:00'
union all
select 2,'EXIT','2011-01-12 21:00:00'
union all
select 2,'ENTER','2011-01-13 01:00:00'
union all
select 2,'EXIT','2011-01-13 18:00:00'
--AND SO ON --

Теперь я пытаюсь сделать запрос, который скажет, как долго один пользователь находился внутри по последнему выходу
что-то вроде

user_id,exited,time_in_hours
1,'2011-01-31 16:00:00',25 
1,'2011-02-10 21:00:00',219
2,'2011-01-12 21:00:00',48
2,'2011-01-13 18:00:00',17

Извините, если это ПЛОХОЙ или РОЖОВЫЙ вопрос, и если это неправильный способ задать такой вопрос. Но я на некоторое время застрял.

Ответы [ 4 ]

1 голос
/ 01 августа 2011

Попробуйте

select a.usr,a.ts enter_date
,min(b.ts) exit_date, datediff(ss,a.ts,min(b.ts)) diff_in_sec
from tempData a
    join tempdata b on a.usr = b.usr and a.ts < b.ts
where a.type='enter' and b.type='exit'
group by a.usr,a.ts
1 голос
/ 01 августа 2011

Предполагая, что

  • сеансы одного пользователя не пересекаются,

  • не может быть записи EXIT без соответствующей записи ENTER,

Вы можете попробовать следующее:

WITH ranked AS (
  SELECT
    user_id,
    type,
    ts,
    rn = ROW_NUMBER() OVER (PARTITION BY user_id, type ORDER BY ts)
  FROM #tempData
)
SELECT
  tx.user_id,
  exited = tx.ts,
  hours = DATEDIFF(HOUR, tn.ts, tx.ts)
FROM ranked tn
  INNER JOIN ranked tx ON tn.user_id = tx.user_id AND tn.rn = tx.rn
WHERE tn.type = 'ENTER'
  AND tx.type = 'EXIT'
1 голос
/ 01 августа 2011

Используя CTE, вы можете сделать

with
  exits as ( select [user_id],ts from #tempData where type='EXIT'),
  entries as ( select [user_id],ts from #tempData where type='ENTER'),
  result as (
select 
RANK() over (Partition by a.user_id,b.ts order by a.ts desc) as i,
a.[user_id],b.ts as 'Last Exited',DATEDIFF(hh,a.ts,b.ts) as [hours]
from
    entries a inner join exits b on b.[User_id]=a.[User_id] and a.ts<b.ts
  )

select user_id,[Last Exited],hours from result where i=1

Это решение, однако, предполагает, что всегда есть выходная запись, чем эта запись всегда соответствует непосредственно предшествующей входной записи

0 голосов
/ 01 августа 2011

Попробуйте это:

SELECT user_id, exitTable.ts AS exited, DATEDIFF(hour, exitTable.ts, enterTable.ts) AS time_in_hours
FROM yourTable enterTable
    INNER JOIN yourTable exitTable
        ON enterTable.user_id = exitTable.user_id
            and exitTable.ts > enterTable.ts
                    and exitTable.type = 'EXIT'
WHERE enterTable.type = 'ENTER'
    and entertable.ts = (SELECT MAX(ts) FROM yourTable WHERE yourTable.user_id = enterTable.user_id AND type = 'ENTER')

Слово объяснения ...

Предложение WHERE ограничивает строки последним ENTER для каждого user_id. Предложение JOIN объединяет эту строку с EXIT, который имеет время после входа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...