Oracle
所以特来此请教各位大佬们有没有好的方法,怎么实现? SQL or PL/SQL ? 不胜感激!
![]() | 1 sadfQED2 2019-10-12 09:14:15 +08:00 U_ID 不是唯一的??那这咋匹配 |
![]() | 2 cwjokaka 2019-10-12 09:17:59 +08:00 JOIN 的结果用 DISTINCT 去重好像可以 |
![]() | 3 xuanbg 2019-10-12 09:21:52 +08:00 这个数据 SQL 没办法做到一一配对。如果数据是有序的,你还能写代码用循环来处理。 |
![]() | 4 xuanbg 2019-10-12 09:22:58 +08:00 非要 SQL 处理,只能存储过程用游标。这种方法严重不推荐! |
![]() | 5 kiracyan 2019-10-12 09:23:52 +08:00 如果 in out 按时间顺序匹配的话 你可以按 U_ID 分组 然后在对应 比如 U_ID=1 有 Gruop1 Group2, 这非唯一对应肯定要先处理原数据的 |
6 ESeanZ 2019-10-12 09:26:11 +08:00 通过 min、max,根据 U_id 获取大当前 in 的最小 out 时间, |
![]() | 7 xuanbg 2019-10-12 09:27:46 +08:00 想了一下,还有一种间接的办法,就是给你的原始数据加一列 group_id,让每一对 IN_OUT 拥有相同且唯一的 id 就行了。然后你就能按 group_id 进行 group by 配对了。 |
8 LeeSeoung 2019-10-12 09:33:01 +08:00 这个还涉及到行转列的问题,就算 sql 写出来也是一坨,建议代码里逻辑处理 |
9 tk2049jq 2019-10-12 09:38:02 +08:00 select a.U_ID, a.DATE_TIME as IN_TIME, b.DATE_TIME as OUT_TIME from (select * from tb_1 where IN_OUT = 'IN') a join (select * from tb_1 where IN_OUT = 'OUT') b on a.U_ID = b.U_ID |
![]() | 10 bluarry 2019-10-12 09:38:41 +08:00 via Android 没用过 oracle,不知道可不可以用 group by 然后排个序 |
![]() | 11 oaix 2019-10-12 09:49:45 +08:00 JOIN 之后再对 U_ID,IN_TIME 做个分组,取最小的 OUT_TIME select U_ID, IN_TIME, min(OUT_TIMES) OUT_TIME from (select U_ID, a.DATE_TIME IN_TIME, b.DATE_TIME OUT_TIMES from TT a join TT b on a.U_ID = b.U_ID and a.DATE_TIME < b.DATE_TIME where a.IN_OUT = 'IN' and b.IN_OUT = 'OUT') t group by U_ID, IN_TIME |
12 wwwwaaanng 2019-10-12 09:52:48 +08:00 两条 sql union 一下? |
13 a87965028 2019-10-12 09:53:08 +08:00 ![]() ;with TT_IN as ( select *, ROW_NUMBER() over(partition by U_ID order by DATE_TIME) as rn from TT where IN_OUT = 'IN' ), TT_OUT as ( select *, ROW_NUMBER() over(partition by U_ID order by DATE_TIME) as rn from TT where IN_OUT = 'OUT' ) select TT_IN.U_ID, TT_IN.DATE_TIME as IN_TIME, TT_OUT.DATE_TIME as OUT_TIME from TT_IN left join TT_OUT on TT_IN.rn = TT_OUT.rn 如果用 sql server 的话,应该就是这么写。可以参考一下 |
![]() | 14 anzu 2019-10-12 10:08:19 +08:00 如果 in out 是严格匹配,有 in 必有 out 的情况下,可以利用行号进行匹配。 这是 mysql 的,假设表名是 inout SELECT t_in.U_ID, t_in.DATE_TIME AS in_time t_out.DATE_TIME AS out_time FROM (SELECT @rowNum1:=@rowNum1 + 1 AS n, i.* FROM `inout` i , (SELECT @rowNum1:=0) tn WHERE in_out = 'in' ORDER BY DATE_TIME ) t_in LEFT JOIN (SELECT @rowNum2:=@rowNum2 + 1 AS n, i.* FROM `inout` i , (SELECT @rowNum2:=0) tn WHERE in_out = 'out' ORDER BY DATE_TIME ) t_out ON t_in.n=t_out.n |
15 a87965028 2019-10-12 10:13:21 +08:00 @a87965028 #13 最后一行写少了 ![]() select TT_IN.U_ID, TT_IN.DATE_TIME as IN_TIME, TT_OUT.DATE_TIME as OUT_TIME from TT_IN left join TT_OUT on TT_IN.rn = TT_OUT.rn and TT_IN.U_ID = TT_OUT.U_ID |
![]() | 16 opengps 2019-10-12 10:17:54 +08:00 不建议合并,看表结构很显然是物联网开关传感器的上报信息。实际上,这么处理会掩盖“漏点”问题。源头建议用程序接收时候处理成时间轴变化状态。也就是说保留原始数据,用程序直接读取源数据加工 |
![]() | 17 Gatsbywl OP @ESeanZ @a87965028 谢谢大家!我写完了。 思路是 1. 先分别选出 IN 和 OUT 的数据 2. 再 LEFT JOIN ON (出的时间晚于进的时间) 3. 最后根据人员和进入时间分组,出的时间排序,每一个进入时间选择最早出的时间( RN = 1 ) SELECT T3.F_ID , T3.F_NAME , T3.IN_T , T3.OUT_T , T3.RN FROM ( SELECT T1.F_ID , T1.F_NAME , T1.DATE_TIME IN_T , T2.DATE_TIME OUT_T , ROW_NUMBER() OVER(PARTITION BY T1.F_ID, T1.DATE_TIME ORDER BY T2.DATE_TIME) RN FROM (SELECT F1.DATE_TIME , F1.F_ID , F1.F_NAME , F1.F_DEPART , F1.IN_OUT FROM ADMIN.FAB_TIME F1 WHERE F1.IN_OUT = '001-正常进入开门' AND F1.DATE_TIME BETWEEN TO_DATE(20191001000000, 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE(20191002000000, 'YYYY-MM-DD HH24:MI:SS') ) T1 LEFT JOIN (SELECT F1.DATE_TIME , F1.F_ID , F1.F_NAME , F1.F_DEPART , F1.IN_OUT FROM ADMIN.FAB_TIME F1 WHERE F1.IN_OUT = '002-正常外出开门' AND F1.DATE_TIME BETWEEN TO_DATE(20191001000000, 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE(20191002000000, 'YYYY-MM-DD HH24:MI:SS') ) T2 ON T1.F_ID = T2.F_ID AND T1.DATE_TIME <= T2.DATE_TIME ORDER BY T1.F_ID,T1.DATE_TIME ) T3 WHERE T3.RN = 1 ; |
18 ESeanZ 2019-10-12 15:14:30 +08:00 @Gatsbywl 老哥你这代码量有点多啊 粗略写了一段 应该没啥毛病(环境 Mysql,某些地方应该不一样) SELECT InTable.u_id,InTable.date_titme AS In_Time, (SELECT MIN(date_titme) FROM demo_1 AS OutTable WHERE OutTable.date_titme>InTable.date_titme AND OutTable.In_Out="Out") AS Out_time FROM demo_1 AS InTable WHERE InTable.In_Out="In" |
19 wqzjk393 2019-10-12 15:43:55 +08:00 case when 啊。。。 |
20 jowenzzzzz 2019-10-12 16:04:37 +08:00 via Android 你是想原表数据转换到查询结果样式吧,不用 join.on 用分析函数应该可以解决 |
![]() | 21 reus 2019-10-13 00:04:50 +08:00 一群人讨论了半天都不知道有窗口函数? select date_time as in_time, lead(date_time, 1) over (partition by u_id order by u_id asc, date_time asc) as out_time from t where in_out = 'in' |