我有这个查询需要大约5分钟来返回结果集,我无法找到更好的方法来做到这一点。有问题的表在任何时候都有大约15或2千万行,其模式可以概括为
create table conversation(
id raw, -- GUID
vendor varchar,
snumber number
rcvdate date
)
我们存储从供应商发送或向供应商发送的消息,每条消息都有一个由所有会话(相关消息集)共享的序列号。问题出现是因为供应商可以拥有父代,并且消息可以包含父代码(我们可以假设我们在查询时知道供应商的代码及其父代码)。假设A和B是2个具有共同父P的供应商,该表可能看起来像
Vendor snumber date
------------------------------
A 1 01-JAN-2012
P 1 02-JAN-2012
A 1 02-JAN-2012
A 2 03-JAN-2012
P 2 03-JAN-2012
B 3 03-JAN-2012
P 3 04-JAN-2012
A 2 04-JAN-2012
我们需要查询来自/到A的最后N条消息,并使用vendor = A OR(供应商= P和另一条供应商= A和相同的狙击手的记录)获取消息,即:
Vendor snumber date
------------------------------
A 1 01-JAN-2012
P 1 02-JAN-2012
A 1 02-JAN-2012
A 2 03-JAN-2012
P 2 03-JAN-2012
A 2 04-JAN-2012
我所做的是将对话存储在临时表T(id,snumber)中,然后返回
select * from (
select * from conversations c
where
exists (select id from T where T.id = C.id) or
( c.vendor=l_parent and exists (select snumber from T where T.snumber=c.snumber )
) where rownum <= l_N
这两个子查询正在扼杀性能。对话表在此示例中包含的所有列中都有索引。 我认为必须是一个聪明的方法来分组这些信息,而不必使用临时表或子查询,但我想不出一个。任何帮助将不胜感激。
答案 0 :(得分:0)
听起来你想要这样的东西:
SQL> select vendor, snumber, rcvdate
2 from (select vendor, snumber, rcvdate,
3 max(case when vendor = 'A' then 'Y' end) over (partition by snumber) has_vendor
4 from conversation
5 where vendor in ( 'A', 'P' )
6 order by rcvdate desc)
7 where has_vendor = 'Y'
8 and rownum <= 100
9 order by rcvdate;
V SNUMBER RCVDATE
- ---------- --------------------
A 1 01-jan-2012 00:00:00
P 1 02-jan-2012 00:00:00
A 1 02-jan-2012 00:00:00
P 2 03-jan-2012 00:00:00
A 2 03-jan-2012 00:00:00
A 2 04-jan-2012 00:00:00
即。
max(case when vendor = 'A' then 'Y' end) over (partition by snumber) has_vendor
如果该狙击手中有'A'供应商,那么你想要为“P”不是供应商返回,否则不会。