Oracle SQL-根据签入和签出记录获取日期之间的差异

Oracle SQL-根据签入和签出记录获取日期之间的差异,sql,oracle,Sql,Oracle,假设我有下表数据 # | USER | Entrance | Transaction Date Time ----------------------------------------------- 1 | ALEX | INBOUND | 2020-01-01 10:20:00 2 | ALEX | OUTBOUND | 2020-01-02 10:00:00 3 | ALEX | INBOUND | 2020-01-04 11:30:00

假设我有下表数据

#  |  USER  |  Entrance |  Transaction Date Time
-----------------------------------------------
1  |  ALEX  |  INBOUND  |  2020-01-01  10:20:00
2  |  ALEX  |  OUTBOUND |  2020-01-02  10:00:00
3  |  ALEX  |  INBOUND  |  2020-01-04  11:30:00
4  |  ALEX  |  OUTBOUND |  2020-01-07  15:00:00
5  |  BEN   |  INBOUND  |  2020-01-08  08:00:00
6  |  BEN   |  OUTBOUND |  2020-01-09  09:00:00
我想知道用户在外逗留的总天数

对于每次入境和出境视为一次行程,超过24小时的每次行程视为2天

下面是我想要的输出:

No. of Days   |   Trips Count
----------------------------------
Stay < 1 day  |   1
Stay 1 day    |   1
Stay 2 days   |   0
Stay 3 days   |   0
Stay 4 days   |   1

我仍然不知道你说的<1天是什么意思,但我已经走了这么远

设置

质疑

结果

您可以使用select max替换6,并重复第二个子查询

我将使用lead和aggregation。假设行正确交错:

select floor( (next_dt - dt) ) as num_days, count(*)
from (select t.*,
             lead(dt) over (partition by user order by dt) as next_dt
      from trips t
     ) t
where entrance = 'INBOUND'
group by floor( (next_dt - dt) )
order by num_days;

注意:这不包括0行。这似乎不是你问题的核心,是一个重要的复杂问题。

到目前为止你尝试过什么?旅行<1天是什么?@user9601310我试图在一张纸上想象它,但我不知道如何构造查询。@Turo trip<1天意味着停留时间少于24小时。2天意味着旅行>24小时,1天正好是24小时?在本例中,您将旅行1分为1天。经过一番思考后,我的猜测是:入境日=出境日?谢谢你的回答,我从中得到了启发。谢谢你的回答,但我认为这将是密集的,因为我的表将非常大。有了正确的索引,这不会那么糟糕,但我自己投票支持@Gordon的答案
select decode (t.days, 0 , 'Stay < 1 day', 1, 'Stay 1 day', 'Stay ' || t.days ||  ' days') Days , count(d.days) Trips_count
FROM (Select Rownum - 1  days From dual Connect By Rownum <= 6) t   left join
(select  extract (day from b.ts - a.ts) + 1 as days from trips a
inner join trips b on a.name = b.name 
and a.entrance = 'INBOUND' 
and b.entrance = 'OUTBOUND' 
and a.ts < b.ts 
and not exists (select ts from trips where entrance = 'OUTBOUND' and ts > a.ts and ts < b.ts)) d
on t.days = d.days
group by t.days order by t.days
DAYS            | TRIPS_COUNT
----------------|------------
Stay < 1 day    | 0
Stay 1 day      | 2
Stay 2 days     | 0
Stay 3 days     | 0
Stay 4 days     | 1
Stay 5 days     | 0
select floor( (next_dt - dt) ) as num_days, count(*)
from (select t.*,
             lead(dt) over (partition by user order by dt) as next_dt
      from trips t
     ) t
where entrance = 'INBOUND'
group by floor( (next_dt - dt) )
order by num_days;