Sql 按限制组中的计数

Sql 按限制组中的计数,sql,oracle,group-by,oracle11g,Sql,Oracle,Group By,Oracle11g,我有一个与获取col1中特定值的计数相关的查询。但我有兴趣将计数限制为3,因为在我的程序逻辑中,我执行的是IF条件: 选择val1,count1 cnt 从选项卡 val1分组 IF cnt=0 --do something ELSIF cnt=1 --do something ELSIF cnt=2 --do something ELSIF cnt>2 --do something ELSE

我有一个与获取col1中特定值的计数相关的查询。但我有兴趣将计数限制为3,因为在我的程序逻辑中,我执行的是IF条件:

选择val1,count1 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,然后告诉甲骨文停止计算val1


e、 g.我在val1中有一个值Item001,对应于val1,我们在另一列val2中有27个组件。但是,当我在val1上运行groupby时,查询应该将val1的出现计数到3,而不是超过3。当达到计数3时,应停止进一步扫描表。它应该跳转到val1中的其他值以获得其计数。

尽管不完全理解,但您的点是什么,计数只有3。。。我认为,您只需计算所需内容的出现次数,然后就可以按原样执行if,不过,如果您不知道您的Oracle版本,请查看以下链接信息是否有帮助:


尽管不明白你的意思,但数到3。。。我认为,您只需计算所需内容的出现次数,然后就可以按原样执行if,不过,如果您不知道您的Oracle版本,请查看以下链接信息是否有帮助:


您可以使用rownum将行数限制为最多3行。
如果使用此选项,则选择将在第3行之后停止,因此您不会计算100000行。您可以使用rownum将行数限制为最多3行。
如果使用此选项,则您的选择将在第3行之后停止,因此您不会计数100000行。要将计数限制为3,请执行以下操作:

select val1, if(cnt > 2, 3, cnt) cnt
from (select val1, count(1) cnt
from tab
group by val1) x

要将计数限制为3,请执行以下操作:

select val1, if(cnt > 2, 3, cnt) cnt
from (select val1, count(1) cnt
from tab
group by val1) x

您应该了解Oracle如何读取数据

引擎从磁盘请求数据块。它不知道下一个街区有什么。例如,它不知道是否有更多的项目001或有新的项目。它应该读取块-其中的所有行。然后,与从磁盘获取块所需的时间相比,再计算一个Item001s或Item999s算不了什么


这是因为行在表中没有排序。引擎不知道“有item001s和Item002s等”,除非您在val1上有一个分区表,但我几乎肯定这对您没有帮助。

您应该了解Oracle如何读取数据

引擎从磁盘请求数据块。它不知道下一个街区有什么。例如,它不知道是否有更多的项目001或有新的项目。它应该读取块-其中的所有行。然后,与从磁盘获取块所需的时间相比,再计算一个Item001s或Item999s算不了什么


这是因为行在表中没有排序。引擎不知道“有item001s和Item002s等”,除非您在val1上有一个分区表,但我几乎肯定这对您没有帮助。

我认为在有限的情况下值得这样做,但假设我们有一个带有ID列的表T1,和另一个表T2,其中ID值出现了若干次,并且您只希望最多统计3次

您可以尝试的是:

 select id,
        (select count(*) from t2 where t2.id = t1.id and rownum <= 3) c_star
 from   t1
但是,您应该明确地将其与更常规的计数方法进行比较

编辑:只需考虑这样的情况,即这可能比完整计数更快

假设你有一个小号码15?设备,每个设备每秒生成10条消息,这些消息被插入到按天分区的表中,并且没有索引。您需要检查每个人是否每天至少记录20条消息

一个分区的完整计数约为1300万行,但由于每个设备的完整计数限制为20行,因此实际上执行了15次完整分区扫描,在扫描了几行之后,这些扫描都将通过rownum限制终止

当然,如果您的设备出现故障,您最终将进行完整扫描


不管怎样,这是我脑子里想不出来的。我并不是说这是一个好主意,但这是可能的。

我认为在有限的情况下,这样做是值得的,但假设我们有一个带有ID列的表T1,还有一个带有ID值的表T2,在某些情况下,您只想数到3次

您可以尝试的是:

 select id,
        (select count(*) from t2 where t2.id = t1.id and rownum <= 3) c_star
 from   t1
但是,您应该明确地将其与更常规的计数方法进行比较

编辑:只需考虑这样的情况,即这可能比完整计数更快

假设你有一个小号码15?设备,每个设备每秒生成10条消息,这些消息被插入到按天分区的表中,并且没有索引。您需要检查每个人是否每天至少记录20条消息

分区的完整计数约为1300万 n行,但由于计数限制为每个设备20行,因此实际上执行了15次完整分区扫描,在扫描了几行之后,这些扫描都将通过rownum限制终止

当然,如果您的设备出现故障,您最终将进行完整扫描

不管怎样,这是我脑子里想不出来的。我不是说这是个好主意,但这是可能的。

我想我不是疯了: 尝一尝

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
它使用标准方案,但这里是 服务很好:

我想我不是疯了: 尝一尝

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
它使用标准方案,但这里是

服务很好:

基本上我们正在统计表中所有val1的出现次数。但我想数到3,然后告诉甲骨文停止计算val1。e、 g.我在val1中有一个值Item001,对应于val1,我们在另一列val2中有27个组件。但是,当我在val1上运行groupby时,查询应该将val1的出现计数到3,而不是超过3。当达到计数3时,应停止进一步扫描表。它应该跳转到val1中的其他值以计数。你不能做你要求的事情。这是你能得到的最接近的。如果你运行这个,我想你会发现它的性能相当好,我们正在计算表中所有val1的出现次数。但我想数到3,然后告诉甲骨文停止计算val1。e、 g.我在val1中有一个值Item001,对应于val1,我们在另一列val2中有27个组件。但是,当我在val1上运行groupby时,查询应该将val1的出现计数到3,而不是超过3。当达到计数3时,应停止进一步扫描表。它应该跳转到val1中的其他值以计数。你不能做你要求的事情。这是你能得到的最接近的。如果你运行这个程序,我想你会发现它运行得很好。不要使用count1-count*是正确的语法。@davidadridge请证明我想说,如果你要偏离记录的标准,那么重点应该放在正在证明的偏差上,你不觉得吗?count1在某种程度上改善了count*吗?不要使用count1-count*是正确的语法。@Davidadridge请证明我想说,如果你要偏离记录的标准,那么重点应该放在证明的偏差上,你不觉得吗?count1在某种程度上改善了count*吗?这是我一直在寻找的一种查询。只是稍微修改一下,这里的t2和t1是一样的。我不知道这怎么会比从表组中选择val1,count*by val1快@FlorinGhita我相信在某些情况下,它会避免访问和计算数据。这在很大程度上取决于基数和索引。当然,这就是存在rownum的原因:我所说的不是OP的情况。分区是我在回答中提到的,但我认为这里不是这样。无论如何,我相信这个问题是不明确的,用户从rownum的发现中获益匪浅:而且+感谢我以某种方式帮助用户:这是我一直在寻找的一种查询。只是稍微修改一下,这里的t2和t1是一样的。我不知道这怎么会比从表组中选择val1,count*by val1快@FlorinGhita我相信在某些情况下,它会避免访问和计算数据。这在很大程度上取决于基数和索引。当然,这就是存在rownum的原因:我所说的不是OP的情况。分区是我在回答中提到的,但我认为这里不是这样。无论如何,我相信这个问题是不明确的,用户从rownum的发现中获益匪浅:而且+我向用户提供的帮助:让我在使用以下两个查询时清除数据库负载,并以两者为例:1。从组织id=1703的oe_订单行_all中选择count1;15递归调用0 db块获取33269一致获取33264物理读取2856重做大小230字节通过SQL*Net发送到客户端278字节通过SQL*Net从客户端接收到客户端2 SQL*Net往返于客户端0排序内存0排序磁盘1已处理行2。从oe_order_lines_all中选择count1,其中org_id=1703和rownumI不理解您在这些评论中向我提出的要求,但它们之间的区别很明显。第二个查询在8个块之后停止,因为您只询问了3行。第一个请求所有行。这几乎与你的问题无关。我不是问你方有什么意见,只是想澄清一点,为什么我只对最多出现3次的值感兴趣,而不必搜索所有表。请参见上面David的回答。让我在使用以下两个查询时清除数据库负载,并以两者为例:1。从组织id=1703的oe_订单行_all中选择count1;15递归调用0 db块获取33269一致获取33264物理读取2856重做大小230字节通过SQL*Net发送到客户端通过SQL*Net从c接收278字节
客户端2 SQL*Net往返客户端0排序内存0排序磁盘1处理的行2。从oe_order_lines_all中选择count1,其中org_id=1703和rownumI不理解您在这些评论中向我提出的要求,但它们之间的区别很明显。第二个查询在8个块之后停止,因为您只询问了3行。第一个请求所有行。这几乎与你的问题无关。我不是问你方有什么意见,只是想澄清一点,为什么我只对最多出现3次的值感兴趣,而不必搜索所有表。见上面大卫的回答。