排名不能在where子句中使用的别名

时间:2015-11-05 15:02:42

标签: sql oracle rank

create table tab1(sno int, name varchar(30), age int);

insert into tab1 values(1, 'abc1', 22);
insert into tab1 values(2, 'abc2', 23);
insert into tab1 values(3, 'xyz', 28);
insert into tab1 values(4, 'abc3', 26);
insert into tab1 values(5, 'abc4', 25);

select sno, name, age, rank() over (order by sno) as ranking from tab1 where
ranking = trunc((select count(*)/2 from tab1)) + 1; //This query is giving error

错误是ORA-00904:"排名":无效标识符

2 个答案:

答案 0 :(得分:3)

您正尝试根据完成所有过滤后计算的值过滤您的选择结果。您需要将其更改为以下内容:

select * from (
  select sno, name, age, rank() over (order by sno) as ranking from tab1 
) where ranking = trunc((select count(*)/2 from tab1)) + 1;

答案 1 :(得分:2)

您的问题是感谢您在select中定义别名,然后您希望按其过滤。您需要使用CTE或子查询:

with cte as (
      select sno, name, age, rank() over (order by sno) as ranking
      from tab1
     )
select cte.*
from cte
where cte.ranking = trunc((select count(*)/2 from tab1)) + 1; 

您似乎想要计算中值。我绝对不会为此目的推荐rank(),因为它处理关系的方式。一个更好的选择是row_number(),所以这非常接近获得中位数。并且,您不需要子查询:

with cte as (
      select sno, name, age, row_number() over (order by sno) as ranking,
             count(*) over () as cnt
      from tab1
     )
select cte.*
from cte
where 2*cte.ranking in (cnt, cnt + 1)

这对于偶数行和奇数行都足够好。

您可能还对MEDIAN()PERCENTILE_DISC()PERCENTILE_CONT()函数感兴趣。