Reputation: 197
I have a old school HR schema which consist of Employees table. The table has a column of salary for employees. Minimum salary is 2100 and maximum is 24000. If I were to find all the thousand salaries (3000,4000,5000...) which are not present in the salary column of the table (between 2100 and 24000) then what should I do ?
I thought of using a FOR loop over the select statement of a cursor then fetching the data through cursor and displaying them. But it throws an error. Following is something which I tried for the mentioned problem :
declare
cursor c1 is
for i in 2000..25000
loop
select salary
from employees where salary<>i;
end loop;
sal number(10);
begin
for cur IN c1
loop
dbms_output.put_line(c1.sal);
end loop;
end;
Above code throws and error saying "Expected instead of "
Anyone with a cure ?
Upvotes: 1
Views: 1355
Reputation: 167867
Here is a pure SQL solution that does not require you to hard-code the lowest and highest salary and uses MINUS
instead of a correlated sub-query:
SELECT min_salary + ( LEVEL - 1 ) * 1000 As salary
FROM (
SELECT MIN( CEIL( salary / 1000 ) * 1000 ) AS min_salary,
MAX( FLOOR( salary / 1000 ) * 1000 ) AS max_salary
FROM employees
)
CONNECT BY min_salary + ( LEVEL - 1 ) * 1000 <= max_salary
MINUS
SELECT salary
FROM employees;
Upvotes: 1
Reputation: 22949
This could be a pl/sql solution, simpler than your attempt; a bit of explanation in the comments:
declare
vNum number;
begin
/* a loop for 2000 ... 25000 would give 2000, 2001, 2002, ... 25000 */
for i in 2..25 loop
/* check if the salary exists */
select count(1)
into vNum
from employees
where salary = i * 1000;
--
/* print the result */
if vNum = 0 then
dbms_output.put_line('Salary ' || i*1000 || ' does not exist');
else
dbms_output.put_line('Salary ' || i*1000 || ' exists');
end if;
end loop;
end;
Notice that this is not an efficient solution, neither the way I would implement this, but I hope it is clear enough to give you some hints to build your procedures.
This could be an SQL solution:
select sal
from (
select (level +1) * 1000 as sal
from dual
connect by (level +1) * 1000 <= 25000
) salaries
where salaries.sal not in ( select salary from employees)
the "tricky" part here is the inner query, used to generate a list of values 2000, 3000, ... 25000
:
select (level +1) * 1000 as sal
from dual
connect by (level +1) * 1000 <= 25000
here I used a NOT IN
, which may not be the perfect choice, but I hope it could be quite self-explanatory; the logic is something like "list all the values in 2000, ... 25000 that are not in the list of salaries".
Upvotes: 3