【问题标题】:Merge two tables based on time根据时间合并两个表
【发布时间】:2020-04-13 07:24:21
【问题描述】:

我是 Oracle SQL 的新手。请通过仅在 Oracle SQL 中为我提供解决方案来帮助我解决此问题。

我们有两个表 LOGINLOGOUT。一个用于登录数据,另一个用于注销数据,如下所述。

登录

LOGIN_TIME                      ID
19-DEC-19 03.59.33.637000000 AM 1
19-DEC-19 06.58.16.318000000 AM 2
19-DEC-19 10.19.26.039000000 AM 2
19-DEC-19 10.26.03.411000000 AM 2
19-DEC-19 01.35.56.006000000 PM 2

注销

LOGOUT_TIME                     ID
19-DEC-19 04.34.22.535000000 AM 1
19-DEC-19 07.52.21.568000000 AM 2
19-DEC-19 02.06.13.585000000 PM 2

我想以这样一种方式合并这两个表,以便我获得带有各自登录和注销时间的 ID。下面提到了预期的输出。

预期输出

ID          LOGIN_TIME                      LOGOUT_TIME
1           19-DEC-19 03.59.33.637000000 AM 19-DEC-19 04.34.22.535000000 AM
2           19-DEC-19 06.58.16.318000000 AM 19-DEC-19 07.52.21.568000000 AM
2           19-DEC-19 10.19.26.039000000 AM (null)
2           19-DEC-19 10.26.03.411000000 AM (null)
2           19-DEC-19 01.35.56.006000000 PM 19-DEC-19 02.06.13.585000000 PM    

提前致谢。

【问题讨论】:

  • 为什么你的输出不正确?
  • 第三行的 LOGOUT_TIME 预计为空。它给了我 19-DEC-19 02.06.13.585000000 PM 的值,这应该是第 5 行的 LOGOUT_TIME。
  • 我看到了,但不明白为什么要从“19-DEC-19 02.06.13.585000000 PM”注销的 3 个可能登录中选择最后一次登录。
  • 如果在表中再添加一个注销19-DEC-19 02.06.20 PM 2 会怎样?
  • LOGIN_TIME 是升序的,所以第三行的 LOGOUT_TIME 必须小于 NEXT ROWS 的 LOGIN_TIME。

标签: sql oracle date join gaps-and-islands


【解决方案1】:

我将您的查询理解为某种差距和孤岛问题。

我会通过unioning 两个表来解决它,然后进行窗口求和以识别组:每次登录时,都会启动一个新组。最后一步是按组聚合。

select
    id,
    min(case when action = 'in'  then dt end) login_time,
    max(case when action = 'out' then dt end) logout_time
from (
    select
        t.*,
        sum(case when action = 'in' then 1 else 0 end)
            over(partition by id order by dt) grp
    from (
        select id, login_time dt, 'in' action from login
        union all select id, logout_time, 'out' from logout
    ) t
) t
group by id, grp
order by id, grp

Demo on DB Fiddle

身份证 |登录时间 | LOGOUT_TIME -: | :-------------------------------- | :-------------------------------- 1 | 19-DEC-19 03.59.33.637000000 上午 | 19 年 12 月 19 日 04.34.22.535000000 上午 2 | 19-DEC-19 06.58.16.318000000 AM | 19-DEC-19 07.52.21.568000000 AM 2 | 19-DEC-19 10.19.26.039000000 上午 | 2 | 19-DEC-19 10.26.03.411000000 上午 | 2 | 19 年 12 月 19 日 01.35.56.006000000 下午 | 19-DEC-19 02.06.13.585000000 下午

【讨论】:

  • 当我运行您的查询时,我得到这样的输出
    ` ID LOGIN_TIME LOGOUT_TIME 1 (null) 19-DEC-19 04.34.22.535000000 AM 1 19-DEC-19 03.59.33.637000000 AM (空) 2 (空) 19-DEC-19 02.06.13.585000000 PM 2 19-DEC-19 06.58.16.318000000 AM (空) 2 19-DEC-19 10.19.26.039000000 AM (空) 2 19-DEC-19 10.26 .03.411000000 AM (null) 2 19-DEC-19 01.35.56.006000000 PM (null) ` 很抱歉我无法以表格形式打印输出。请帮助我输出。
  • @Devudu:当我对您的样本数据进行测试时,这产生了预期的结果(请参阅我的答案中的 DB Fiddle 链接)。如果这对您不起作用,您能否设置一个可以看到问题的 DB Fiddle?
  • @Devudu:以防万一,请您确认一下您的数据库表中LOGIN_TIMELOGOUT_TIME 列的数据类型是什么?
  • 登录和注销时间的时间戳和 id 的 Varchar
  • 得到它只是在联合声明中添加了修剪(id)。不要现在为什么将其视为不同的 id。
【解决方案2】:

只是如果登录时间小于注销时间,您需要检查大小写。

    Select id, l.login_time,
    Case when
      l.login_time<lo.logut_time 
     Then lo.logout_time end
    From login l left join logout lo
    On  l.id=lo.id

【讨论】:

    猜你喜欢
    • 2021-09-10
    • 2022-11-02
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多