结合 Rownum 和 Distinct

Combine Rownum with Distinct

我在 Oracle 中有这个查询:

Select run_date 
from (select distinct run_date 
      from transactions where primary_customer_id ='cliente'
      group by run_date 
      order by run_date desc);

我需要显示第二行,但是用行号是不可能的。

Select run_date, rownum r_ from(select distinct run_date 
                              from transactions 
                              where primary_customer_id ='cliente' 
                              group by run_date 
                              order by run_date desc))
where r_ = 2;

有什么可以帮我的吗?

非常感谢。

你不应该在 where 中使用别名,所以使用 rownum 而不是别名 r_

Select run_date, rownum r_ from(
      select distinct run_date 
      from transactions 
      where primary_customer_id ='cliente' 
      order by run_date desc)) t
where rownum = 2; 

并且使用 distinct 你不需要分组依据。

Group by 用于聚合函数,如 min() max() count() ...

你可以不使用子查询直接尝试

      select distinct run_date 
      from transactions 
      where primary_customer_id ='cliente' 
      and rownum =2
      order by run_date desc

rownum 可以,但需要一定的准确性:

select run_date
from 
  ( select run_date, rownum r# 
    from 
      ( select run_date 
        from transactions 
        where primary_customer_id ='cliente' 
        group by run_date 
        order by run_date desc
      )
  )
where r# = 2;

遗憾的是,虽然它确实有效,但没有人能保证它会永远有效。这个查询的结果在理论上是不可预测的,使用它的技巧在新版本的 RDBMS 内核中可能会失败,就像 Oracle 10g 和 GROUP BY 排序一样。所以最好使用像

这样的东西
select min(run_date)
from 
  ( select lead(run_date) over (order by run_date) run_date
    from 
      ( select distinct run_date 
        from transactions 
        where primary_customer_id ='cliente'
      )
  )
where r# = 2;

P.S。无论如何,像您那样将 DISTINCT 与 GROUP BY 组合在一起是口吃。

您不必同时使用 GROUP BYDISTINCT。另请注意,简单的 ROWNUM = 2 在 Oracle 中永远不会得到满足。

这适用于 10g 和 11g。

WITH r
     AS (  SELECT DISTINCT run_date
             FROM transactions
            WHERE primary_customer_id = 'cliente'
         ORDER BY run_date DESC)
SELECT run_date
  FROM (SELECT run_date, ROWNUM rn FROM r)
 WHERE rn = 2;

在 Oracle 12c 中,您可以通过这样的查询获得相同的结果。

 SELECT run_date
    FROM r  -- without ORDER BY inside cte, r
ORDER BY run_date DESC
  OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY;