在子查询之间的 ORACLE 连接语句中选择顶部记录

Posted

技术标签:

【中文标题】在子查询之间的 ORACLE 连接语句中选择顶部记录【英文标题】:selecting top record in ORACLE join statement between subqueries 【发布时间】:2012-12-18 02:29:54 【问题描述】:

我想请你帮忙构造一条 ORACLE SQL 语句:

使用工作表如下

Object | Operation | Time  
A      | Move      | 12:01  
B      | Move      | 12:02  
C      | Pickup    | 12:03  
D      | Move      | 12:04  
B      | Pickup    | 12:05  

得到如下结果表。

Object | Operation | Time  | Cause  
A      | Move      | 12:01 | C  
B      | Move      | 12:02 | C  
D      | Move      | 12:04 | B 

这是为了找出哪个 Pickup 操作导致了每个 Move 操作。 “原因”列必须包含紧邻移动操作时间最短的取件作业记录的对象。

我有以下一些想法,但不知道怎么做。 -。它需要在 Move 的子查询和 Pickup 的子查询之间使用 join 语句 -。 Pickup 的子查询必须按要加入的移动记录进行分区 -。只能从 Pickup 子查询的每个分区中选择 top 记录

【问题讨论】:

不会minimum(colName) 解决您的第三个要求吗?祝你好运。 “时间”列的数据类型? @shellter 必须为每条 Move 记录的 MIN() @techdo 它在 DATE 虽然我只在示例中写了 HH:MM 【参考方案1】:

这是我的尝试:

select  m.object, m.operation, m.time, 
  max(p.object) keep (dense_rank first order by p.time) cause,
  max(p.time) keep (dense_rank first order by p.time) cause_time
from a m
join a p on (p.time > m.time)
where m.operation = 'Move'
and p.operation = 'Pickup'
group by m.object, m.operation, m.time;

见SQLFiddle

我已将列时间设为数字,这并不重要,因为它是可排序的。

我已将表格分成两部分,即 Moves 和 Pickups,并且按时进行连接,pickup 的时间大于 move 的时间。 (这种类型的连接在性能上不是很好)。然后我choose 最小的皮卡time(first 子句,order by p.time)。

【讨论】:

感谢您不仅提供SQL语句,还提供友好的解释:)【参考方案2】:

这是我的尝试:

select object, operation, time, t.pobject
from a join 
   (select object pobject, time cur, lag(time,1, 0) over (order by time  ) prev 
      from a
     where operation = 'Pickup')t 
on a.time > t.prev and a.time <= t.cur
where operation = 'Move';

Here is a sqlfiddle

【讨论】:

+1,但我仍然需要更多的研究来了解它是如何工作的 :) @ShonerSul,解释:内部选择只取'Pickup'行并使用lag函数获取上一条记录的时间(所以基本上现在我有了所有的开始时间和结束时间'移动')。然后我可以将它与所有“移动”记录一起加入【参考方案3】:

有一个老派的

select j1.Object, j1.Operation, j1.Time, substr(min(j2.Time || j2.Object), 6) Cause
from job j1, job j2
where j1.Operation like 'Move'
  and j1.Time < j2.Time
  and j2.Operation like 'Pickup'
group by j1.Object, j1.Operation, j1.Time

这里是SQLFiddle

【讨论】:

喜欢这个,不使用花哨的“平台特定”功能。有人可以使用纯 SQL 吗? @cha 挺纯的 :) 把 substr() 换成 substring() 就可以得到 ANSI SQL 的解决方案了。 虽然我接受了另一个答案,因为它可以包含取件记录的其他列,但我个人更喜欢这个简单的答案:) @Shoner Sul 这个也可以包含任何列 ;) substr(min(j2.Time || j2.Operation), substr(min(j2.Time || j2.Time), substr( min(j2.Time || j2.Cause) :)

以上是关于在子查询之间的 ORACLE 连接语句中选择顶部记录的主要内容,如果未能解决你的问题,请参考以下文章

选择带有“is null”子句的查询和子选择/左连接不返回结果

如何在子查询中使用 select 中的值?

ORA-00936 在 oracle 选择语句中使用日期函数时

在 SQL 子查询中使用多个表进行 Oracle 半联接

Oracle查询转换之连接谓词推入

Oracle学习篇之SQL语句的优化