Home » SQL & PL/SQL » SQL & PL/SQL » Please help in understanding this SQL statement for getting the Top 3 salaried employees
Please help in understanding this SQL statement for getting the Top 3 salaried employees [message #167234] Wed, 12 April 2006 00:34 Go to next message
sudhirbhatti
Messages: 5
Registered: June 2005
Location: Noida,India
Junior Member

I have a table which gives employees and their salaries.
I want the details of top 3 salaried employees.
There are two ways of doing it.
One through analytical func. and the other is given below.

Can someone explain how does this query works internally?
Which portion is evaluated first?
how the comparison is being done between the e1 & e2 values?


select e1.name, e1.sal from emp1 e1,emp1 e2
where e1.sal<=e2.sal
group by e1.sal,e1.name
having count(e2.sal)<=3;
Re: Please help in understanding this SQL statement for getting the Top 3 salaried employees [message #167292 is a reply to message #167234] Wed, 12 April 2006 05:07 Go to previous messageGo to next message
rajavu1
Messages: 1574
Registered: May 2005
Location: Bangalore , India
Senior Member

Just have a look ...

15:25:59 SQL>  SELECT e.ename, e.sal from  emp e;

ENAME             SAL
---------- ----------
JONES            2975
BLAKE            2850
SCOTT            3000
KING             5000
FORD             3000

15:23:04 SQL> SELECT e.ename, e.sal,e1.sal FROM emp e,emp e1
15:23:14   2  WHERE e.sal<=e1.sal
15:23:14   3  order by  e.ename, e.sal;

ENAME             SAL        SAL
---------- ---------- ----------
BLAKE            2850       2975
BLAKE            2850       2850
BLAKE            2850       3000
BLAKE            2850       5000
BLAKE            2850       3000
FORD             3000       3000
FORD             3000       3000
FORD             3000       5000
JONES            2975       2975
JONES            2975       3000
JONES            2975       3000
JONES            2975       5000
KING             5000       5000
SCOTT            3000       3000
SCOTT            3000       5000
SCOTT            3000       3000

16 rows selected.

Elapsed: 00:00:01.00
15:23:15 SQL>  SELECT e.ename, e.sal,e1.sal FROM emp e,emp e1
15:23:23   2   WHERE e.sal<=e1.sal
15:23:23   3   GROUP BY  e.ename, e.sal,e1.sal
15:23:23   4   HAVING count(e1.sal)<=3;

ENAME             SAL        SAL
---------- ---------- ----------
FORD             3000       3000
FORD             3000       5000
KING             5000       5000
BLAKE            2850       3000
BLAKE            2850       5000
BLAKE            2850       2850
BLAKE            2850       2975
JONES            2975       3000
JONES            2975       5000
JONES            2975       2975
SCOTT            3000       3000
SCOTT            3000       5000

12 rows selected.

Elapsed: 00:00:00.06
15:23:24 SQL> ed
Wrote file afiedt.buf

  1   SELECT e.ename, e.sal  FROM emp e,emp e1
  2   WHERE e.sal<=e1.sal
  3*  GROUP BY  e.ename, e.sal
15:23:42 SQL> /

ENAME             SAL
---------- ----------
FORD             3000
KING             5000
BLAKE            2850
JONES            2975
SCOTT            3000

Elapsed: 00:00:00.02
15:23:44 SQL> ed
Wrote file afiedt.buf

  1   SELECT e.ename, e.sal,count(*)  FROM emp e,emp e1
  2   WHERE e.sal<=e1.sal
  3*  GROUP BY  e.ename, e.sal
15:24:23 SQL> /

ENAME             SAL   COUNT(*)
---------- ---------- ----------
FORD             3000          3
KING             5000          1
BLAKE            2850          5
JONES            2975          4
SCOTT            3000          3

Elapsed: 00:00:00.02
15:24:25 SQL> ed
Wrote file afiedt.buf

  1   SELECT e.ename, e.sal,count(*)  FROM emp e,emp e1
  2   WHERE e.sal<=e1.sal
  3   GROUP BY  e.ename, e.sal
  4*  having count(*)<=3
15:25:10 SQL> /

ENAME             SAL   COUNT(*)
---------- ---------- ----------
FORD             3000          3
KING             5000          1
SCOTT            3000          3

Elapsed: 00:00:00.02
15:25:12 SQL> ed
Wrote file afiedt.buf

  1   SELECT e.ename, e.sal,count(distinct e1.sal)  FROM emp e,emp e1
  2   WHERE e.sal<=e1.sal
  3   GROUP BY  e.ename, e.sal
  4*  having count(distinct e1.sal)<=3
15:25:58 SQL> /

ENAME             SAL COUNT(DISTINCTE1.SAL)
---------- ---------- ---------------------
FORD             3000                     2
KING             5000                     1
JONES            2975                     3
SCOTT            3000                     2

Elapsed: 00:00:00.03
15:25:59 SQL>


Is it clear now ... ?

Thumbs Up
Rajuvan.

[Updated on: Wed, 12 April 2006 05:14]

Report message to a moderator

icon12.gif  Re: Please help in understanding this SQL statement for getting the Top 3 salaried employees [message #167325 is a reply to message #167234] Wed, 12 April 2006 07:40 Go to previous messageGo to next message
sauami
Messages: 54
Registered: October 2005
Location: india
Member
Hi,

You can do the same thing by using given query this will easily under stand by you
-----------
select ename, sal from (select distinct(ename), sal from emp1 order by sal desc) where rownum<=3;
--------------------------------------

Hint: the concept of nested query is: nested query become a output for out main query, so nested(second query evaluatej first).

Thanks,
Saurabh
saurabhraj1978@hotpop.com
Re: Please help in understanding this SQL statement for getting the Top 3 salaried employees [message #167351 is a reply to message #167234] Wed, 12 April 2006 09:53 Go to previous message
smartin
Messages: 1803
Registered: March 2005
Location: Jacksonville, Florida
Senior Member
Rajavu1 is on the right track, and has taken the right approach. Basically break it up into pieces and try to visualize those pieces and how they fit together. Here is another demo in case it helps.

I'll also say that this must probably be for a class, because it is an odd way in my mind to come up with the answer. But, that is the great thing about SQL is that there are lots of ways to attack a problem, and it is helpful to be aware of the different approaches.

MYDBA > 
MYDBA > -- Uses a strange way to get details of people with the top three salaries.
MYDBA > -- I would prefer to use analytics and/or inline views, and would never have
MYDBA > -- come up with this approach on my own, although it does actually work.
MYDBA > -- To understand how it works, deconstruct the query one step at a time.
MYDBA > 
MYDBA > -- original query, modified to use the standard emp table in the scott schema
MYDBA > 
MYDBA > select e1.ename, e1.sal
  2  from emp e1,emp e2
  3  where e1.sal<=e2.sal
  4  group by e1.sal,e1.ename
  5  having count(e2.sal)<=3;

ENAME             SAL
---------- ----------
KING             5000
SCOTT            3000
FORD             3000

MYDBA > 
MYDBA > -- when you have a function in the having clause, but not in the select
MYDBA > -- clause, you can add it to the select clause without any other changes
MYDBA > 
MYDBA > select e1.ename, e1.sal, count(e2.sal)
  2  from emp e1,emp e2
  3  where e1.sal<=e2.sal
  4  group by e1.sal,e1.ename
  5  having count(e2.sal)<=3;

ENAME             SAL COUNT(E2.SAL)
---------- ---------- -------------
KING             5000             1
SCOTT            3000             3
FORD             3000             3

MYDBA > 
MYDBA > -- the query concept is really backwards, because the e2 salaries are
MYDBA > -- the ones that are greater than the e1 salaries, meaning you want at
MYDBA > -- most 3 (<=3). without the having clause, all of counts are shown.
MYDBA > 
MYDBA > select e1.ename, e1.sal, count(e2.sal)
  2  from emp e1,emp e2
  3  where e1.sal<=e2.sal
  4  group by e1.sal,e1.ename;

ENAME             SAL COUNT(E2.SAL)
---------- ---------- -------------
TURNER           1500             8
ALLEN            1600             7
KING             5000             1
MARTIN           1250            11
WARD             1250            11
MILLER           1300             9
SMITH             800            14
ADAMS            1100            12
CLARK            2450             6
SCOTT            3000             3
BLAKE            2850             5
JAMES             950            13
JONES            2975             4
FORD             3000             3

14 rows selected.

MYDBA > 
MYDBA > -- here it is without the group by, but ordered by the group by columns,
MYDBA > -- and showing what is being counted by the group by count function: e2 sal
MYDBA > 
MYDBA > select e1.ename, e1.sal, e2.sal
  2  from emp e1,emp e2
  3  where e1.sal<=e2.sal
  4  order by e1.sal, e1.ename;

ENAME             SAL        SAL
---------- ---------- ----------
SMITH             800       1250
SMITH             800       1250
SMITH             800       1100
SMITH             800        950
SMITH             800        800
SMITH             800       1300
SMITH             800       5000
SMITH             800       1600
SMITH             800       2450
SMITH             800       2850
SMITH             800       2975
SMITH             800       3000
SMITH             800       3000
SMITH             800       1500
JAMES             950       1300
JAMES             950       1250
JAMES             950       1250
JAMES             950       1100
JAMES             950        950
JAMES             950       1500
JAMES             950       5000
JAMES             950       3000
JAMES             950       3000
JAMES             950       2975
JAMES             950       2850
JAMES             950       2450
JAMES             950       1600
ADAMS            1100       1100
ADAMS            1100       1250
ADAMS            1100       1250
ADAMS            1100       1300
ADAMS            1100       3000
ADAMS            1100       5000
ADAMS            1100       2975
ADAMS            1100       2850
ADAMS            1100       2450
ADAMS            1100       1600
ADAMS            1100       1500
ADAMS            1100       3000
MARTIN           1250       1250
MARTIN           1250       1250
MARTIN           1250       1300
MARTIN           1250       1500
MARTIN           1250       1600
MARTIN           1250       2450
MARTIN           1250       2850
MARTIN           1250       2975
MARTIN           1250       3000
MARTIN           1250       3000
MARTIN           1250       5000
WARD             1250       1250
WARD             1250       1250
WARD             1250       1300
WARD             1250       1500
WARD             1250       1600
WARD             1250       5000
WARD             1250       2850
WARD             1250       2975
WARD             1250       3000
WARD             1250       3000
WARD             1250       2450
MILLER           1300       1500
MILLER           1300       1300
MILLER           1300       1600
MILLER           1300       5000
MILLER           1300       3000
MILLER           1300       3000
MILLER           1300       2975
MILLER           1300       2850
MILLER           1300       2450
TURNER           1500       1500
TURNER           1500       3000
TURNER           1500       3000
TURNER           1500       2975
TURNER           1500       2850
TURNER           1500       2450
TURNER           1500       1600
TURNER           1500       5000
ALLEN            1600       1600
ALLEN            1600       5000
ALLEN            1600       3000
ALLEN            1600       3000
ALLEN            1600       2975
ALLEN            1600       2850
ALLEN            1600       2450
CLARK            2450       3000
CLARK            2450       2975
CLARK            2450       2850
CLARK            2450       2450
CLARK            2450       3000
CLARK            2450       5000
BLAKE            2850       3000
BLAKE            2850       3000
BLAKE            2850       2975
BLAKE            2850       2850
BLAKE            2850       5000
JONES            2975       2975

ENAME             SAL        SAL
---------- ---------- ----------
JONES            2975       3000
JONES            2975       3000
JONES            2975       5000
FORD             3000       5000
FORD             3000       3000
FORD             3000       3000
SCOTT            3000       5000
SCOTT            3000       3000
SCOTT            3000       3000
KING             5000       5000

107 rows selected.

MYDBA > 
MYDBA > -- and here is the raw data so can visually double check the results
MYDBA > 
MYDBA > select e1.ename, e1.sal
  2  from emp e1
  3  order by e1.sal desc;

ENAME             SAL
---------- ----------
KING             5000
FORD             3000
SCOTT            3000
JONES            2975
BLAKE            2850
CLARK            2450
ALLEN            1600
TURNER           1500
MILLER           1300
WARD             1250
MARTIN           1250
ADAMS            1100
JAMES             950
SMITH             800

14 rows selected.

MYDBA > 
MYDBA > set echo off;

Previous Topic: Percentage sql..
Next Topic: good tutorial sites
Goto Forum:
  


Current Time: Mon Sep 08 06:37:31 CDT 2025