我有查询与获取col1中特定值的计数有关。但我有兴趣将计数限制为3,因为在我的程序逻辑中,我正在执行IF条件:
选择val1,count(1)cnt 来自标签 按val1分组;
IF cnt=0
--do something
ELSIF cnt=1
--do something
ELSIF cnt=2
--do something
ELSIF cnt>2
--do something
ELSE
--do something
END IF;
我不想继续计算出现超过2的值,因为它在这么大的桌子上会产生额外的开销' TAB'。
我想要数到3,然后告诉oracle再停止计数val1。
e.g。我在val1中有一个值Item001,对应于val1,我们在另一列val2中有27个组件。但是当我在val1上运行group by时,查询应该将val1的出现次数计算到3,而不是高于3。它应该在达到计数3时再停止扫描表。它应该跳转到val1中的其他值以获得计数。
答案 0 :(得分:3)
我认为有一组有限的情况值得这样做,但是假设我们确实有一个带有ID列的表T1,以及另一个带有ID值的表T2,而且你只想计算最多3次。
你可能会尝试的是:
select id,
(select count(*) from t2 where t2.id = t1.id and rownum <= 3) c_star
from t1
http://sqlfiddle.com/#!4/1ab50/1/0
但是你应该根据更常规的计数方法确定基准。
编辑:只考虑可能比完整计数更快的情况。
假设您有少量(15?)设备,每个设备每秒生成十条消息,这些消息将插入到按日分区的表中,并且未编入索引。你想检查每个人每天至少记录20条消息。
分区的完整计数大约为1300万行,但由于每个设备的计数限制为20行,因此实际执行15次完整分区扫描,这些扫描全部将在几行之后终止(通过rownum限制)已扫描过。
当然,如果您的设备出现故障,您最终会进行全面扫描。
无论如何,这只是我的头顶。我不是说这是一个好主意,但它是可能的。
答案 1 :(得分:1)
您应该了解Oracle如何读取数据。
引擎要求磁盘上的数据块。它不知道下一个街区是什么。例如,它不知道是否有更多“Item001”或有新项目。它应该读取块 - 其中的所有行。然后,再计算一个Item001s或Item999s与从磁盘获取块所需的时间相比没什么。
这是因为表中没有排序行。引擎不知道'有item001s并且有Item002s等',除了你在val1上有一个分区表,但我几乎肯定这对你没用。
答案 2 :(得分:0)
尽管不完全理解是你的点数只有3 ...我认为你只需要计算你想要的事件然后你可以执行你的if,但是看看是否有以下链接信息可以提供帮助(不知道您的Oracle版本):
http://www.orafaq.com/faq/how_does_one_select_the_top_n_rows_from_a_table
答案 3 :(得分:0)
您可以使用rownum将行限制为最多3。 如果您使用此选项,那么您的选择将在第3行之后停止,因此您不会计算100000行。
答案 4 :(得分:0)
要将计数限制为3,请执行以下操作:
select val1, if(cnt > 2, 3, cnt) cnt
from (select val1, count(1) cnt
from tab
group by val1) x
答案 5 :(得分:0)
猜猜我不是疯了:) 品尝它。
select mgr, (next_empno + next2_empno + 1) cnt
from (
SELECT empno, mgr,
FIRST_VALUE(empno) OVER (PARTITION BY mgr ORDER BY empno) first_empno,
LEAD(SIGN(empno), 1, 0) OVER (PARTITION BY mgr ORDER BY empno) next_empno,
LEAD(SIGN(empno), 2, 0) OVER (PARTITION BY mgr ORDER BY empno) next2_empno
FROM emp
)
where first_empno = empno
它使用的是标准方案,但这里是 SQLFiddle(非常好的服务:))