Oracle SQL 选择不同查询返回特定行数

发布于 2024-11-28 23:17:59 字数 568 浏览 1 评论 0原文

我在 Oracle 数据库中有一个表,其中包含时间戳列 nextTime 和字符串列 destName。还有更多列,但在本例中只有这两列相关。我正在尝试设计一个查询,该查询将返回具有特定时间间隔内的 nextTime 的不同 destName,并且返回的行数应最大为 1000。当间隔内有超过一千个不同的 destName 时,我希望查询返回一千行,不多也不少。

我实际上有一个正在运行的查询,但它太慢了:

select destName 
from (select /*+ index(tblDestNames tbldestnames_destname)*/ distinct destName
from (select /*+ index(tblDestNames tbldestnames_nextTime)*/ destName
from tblDestNames 
where nextTime < :1 and nextTime >= :2 and destName is not null)) 
where rownum <= 1000; 

非常感谢任何有关如何设计更智能的查询或如何优化现有查询的想法。

I have a table in an Oracle database with a timestamp column nextTime and a string column destName. There are more columns as well, but only these two are relevant in this case. I'm trying to design a query that will return distinct destName having nextTime within a specific interval and the returned number of rows should be maximum one thousand. When there are more than one thousand distinct destName within the interval I want the query to return one thousand rows, netiher more nor less.

I actually have a query that is working, but it is way too slow:

select destName 
from (select /*+ index(tblDestNames tbldestnames_destname)*/ distinct destName
from (select /*+ index(tblDestNames tbldestnames_nextTime)*/ destName
from tblDestNames 
where nextTime < :1 and nextTime >= :2 and destName is not null)) 
where rownum <= 1000; 

Any ideas on how to design a smarter query or how to optimize this exisiting one are very much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心碎的声音 2024-12-05 23:17:59

我不确定是否有理由不将查询简化为这样:

select destName 
from (
    select distinct destName
    from tblDestNames 
    where nextTime < :1 and nextTime >= :2 and destName is not null
    )
where rownum <= 1000; 

但是,这不会解决您的性能问题。问题是这样的:

where rownum <= 1000

通过用“rank”和“over”替换 rownum,您会得到类似的结果:

select distinct destName
from (
    select
       destName
    from
       (select destName, rank()
        over (order by destName desc ) rnk
        from tblDestNames
        where nextTime < :1 and nextTime >= :2 and destName is not null) 
    where rnk <= 1000;
    )

好处是,使用“over”您可以选择将显示的结果的顺序和不会显示的结果的顺序。

编辑:实际上它可以进一步简化为:

select
   distinct destName
from
   (select destName, rank()
    over (order by destName desc ) rnk
    from tblDestNames
    where nextTime < :1 and nextTime >= :2 and destName is not null) 
where rnk <= 1000;

I am not sure that there is a reason not to simplify the query to this:

select destName 
from (
    select distinct destName
    from tblDestNames 
    where nextTime < :1 and nextTime >= :2 and destName is not null
    )
where rownum <= 1000; 

However, this will not solve your performance issue. The problem is this:

where rownum <= 1000

By replacing rownum with 'rank' and 'over' you would get something like:

select distinct destName
from (
    select
       destName
    from
       (select destName, rank()
        over (order by destName desc ) rnk
        from tblDestNames
        where nextTime < :1 and nextTime >= :2 and destName is not null) 
    where rnk <= 1000;
    )

The bonus is that with 'over' you choose the order of the results that will show and the ones that will not show.

EDIT: Actually it can be further simplified into:

select
   distinct destName
from
   (select destName, rank()
    over (order by destName desc ) rnk
    from tblDestNames
    where nextTime < :1 and nextTime >= :2 and destName is not null) 
where rnk <= 1000;
女中豪杰 2024-12-05 23:17:59

我学到的东西

  1. 你应该把执行计划优化留给RDBMS,除非你真的更了解
  2. 没有必要从最里面的子查询返回重复的名称更

简单的查询具有稍微不同的语义:

SELECT destName
FROM (SELECT DISTINCT destName
      FROM tblDestNames
      WHERE destName IS NOT NULL 
        AND nextTime NOT BETWEEN :1 and :2)
WHERE rownum <= 1000;

请注意,BETWEEN是包容性的,即< code>x BETWEEN y AND z 等于 y <= x <= z。要排除上限,您必须按照您的方式进行操作,或者将参数 :2 减少 nextTime 的单位之一。

Things I picked up

  1. You should leave execution plan optimization to the RDBMS unless you really know better
  2. There's no need to return duplicate names from the innermost subquery

Simpler query with slighly different semantics:

SELECT destName
FROM (SELECT DISTINCT destName
      FROM tblDestNames
      WHERE destName IS NOT NULL 
        AND nextTime NOT BETWEEN :1 and :2)
WHERE rownum <= 1000;

Note that BETWEEN is inclusive i.e. x BETWEEN y AND z equals y <= x <= z. To exclude the upper bound you'll either have to do it the way you did or decrement the parameter :2 by one of what ever unit nextTime is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文