Thread: Select subset of rows
Hi folks, I have this table CREATE TABLE EMPLOYEE (ID_EMP INT4 PRIMARY KEY, NAME VARCHAR(35), SALARY NUMERIC(5,2)); I want to select only the employees' names who have the 5 highest salaries. Paulo Siqueira
Of course immediately after sending the last message and logging off my ISP I figured out the simpler way for the third one: begin; select salary into temp saltemp from employee order by salary desc limit 5; select name from employee where exists (select * from saltemp wheresaltemp.salary=employee.salary); end; Stephan Szabo sszabo@bigpanda.com On Sun, 27 Aug 2000, Paulo Roberto Siqueira wrote: > Hi folks, > > I have this table > > CREATE TABLE EMPLOYEE (ID_EMP INT4 PRIMARY KEY, NAME VARCHAR(35), SALARY > NUMERIC(5,2)); > > I want to select only the employees' names who have the 5 highest salaries. > > > > > Paulo Siqueira >
On Sun, 27 Aug 2000, Paulo Roberto Siqueira wrote: > Hi folks, > > I have this table > > CREATE TABLE EMPLOYEE (ID_EMP INT4 PRIMARY KEY, NAME VARCHAR(35), SALARY > NUMERIC(5,2)); > > I want to select only the employees' names who have the 5 highest salaries. Well, that depends on what you want to do in case of duplicate salaries. If you don't care about duplicate salaries, and you don't mind the possibility of non-deterministic responses in some cases: select name from employee order by salary desc limit 5; If you want to take the 5 highest salary values and find however many people have those salaries, I think this works: begin; select distinct salary into temp saltemp from employee order by salary desc limit 5; select name from employee where exists (select * from saltemp wheresaltemp.salary=employee.salary); end; If you want to get at least 5 people but don't want to cut off at 5 if the 5th, 6th, etc people are tied, I'm sure there's a better way, and I probably made at least one mistake in writing this out, but... begin; select distinct salary into temp saltemp from employee order by salary desc limit 5; select salary, count(*) into temp saltemp2 from employeewhere exists(select * from saltemp where saltemp.salary=employee.salary)group by salary; select saltemp2.salary, sum(case when saltemp2_2.salary<=saltemp2.salary then 0 else saltemp2_2.count end) into temp saltemp3from saltemp2,saltemp2 saltemp2_2 group bysaltemp2.salary; select name from employee,saltemp3 where employee.salary=saltemp3.salary and saltemp3.sum<5 order by employee.salarydesc; end;
On Sun, 27 Aug 2000, Stephan Szabo wrote: > > Of course immediately after sending the last message and logging off my > ISP I figured out the simpler way for the third one: > > begin; > select salary into temp saltemp from employee order by salary desc > limit 5; > select name from employee where exists (select * from saltemp where > saltemp.salary=employee.salary); > end; > > Stephan Szabo > sszabo@bigpanda.com > I wonder if the following might be a bit faster? Or would it be slower? select salary into temp saltemp from employee order by salary desc limit 5; select min(salary) as minsal into test minsal from saltemp; select name, salary from employee, minsalwhere salary >= minsal; I don't know the speed difference between my second select and your subselect within an EXISTS clause might be. Just a thought, John
On Sun, 27 Aug 2000, John McKown wrote: > On Sun, 27 Aug 2000, Stephan Szabo wrote: > > > > > Of course immediately after sending the last message and logging off my > > ISP I figured out the simpler way for the third one: > > > > begin; > > select salary into temp saltemp from employee order by salary desc > > limit 5; > > select name from employee where exists (select * from saltemp where > > saltemp.salary=employee.salary); > > end; > > > > Stephan Szabo > > sszabo@bigpanda.com > > > > I wonder if the following might be a bit faster? Or would it be slower? > > select salary into temp saltemp from employee order by salary desc > limit 5; > > select min(salary) as minsal into test minsal from saltemp; > > select name, salary from employee, minsal > where salary >= minsal; > > I don't know the speed difference between my second select and your > subselect within an EXISTS clause might be. Not sure. Probably depends on if the subplan/seq scan for the subquery on the one is more or less expensive than the time on the additional query and processing for the query with the min. Actually, i guess you might be able to use offset in there to get rid of the second query too... if you do like select salary into temp saltemp from employee order by salary desclimit 1 offset 4; you can probably get the 5th one right out.