2017-01-11 21 views
1

私はEmployeesテーブルで構成される古い学校のHRスキーマを持っています。表には従業員の給与の列があります。最低給与は2100で最大は24000です。私がテーブルの給与欄(2100から24000まで)にない1000の給与(3000,4000,5000 ...)をすべて見つけたら、どうすればよいですか?SELECT文のFORループを使用して複数のデータをカーソルでフェッチする方法はありますか?

私は、カーソルのselect文にFORループを使用し、カーソルを介してデータを取り出して表示することを考えました。しかし、それはエラーを投げる。以下の私が言及した問題のためにしようとしたものです:治療法と

誰でも「の代わりに予想される」と言って投げるとエラーコードの上に

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; 

+0

なぜ「FORループを使用してカーソルスルー」?数値範囲内の欠損値をリストする方法が必要なように思えます。カーソル定義は有効なSQLを使用しなければならないので、 'for'ではなく' select'または 'with'で始まる必要があります。 –

+0

はいそれは常にエラーを投げた - 「期待された」は「for」の代わりに「行番号で」を選択する。これは、カーソル定義が最初にselect文を期待していることを明確にしています。 – hashir

答えて

1

ここではハードコードにあなたを必要としない純粋なSQLソリューションは、最低と最高の給料で、相関サブクエリの代わりにMINUSを使用しています。

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; 
+0

クイックレスポンスMT0をありがとう。あなたが提供するソリューションは、非常にクールで効率的なものです。私はハードコーディングの問題をスワイプすることができます。コードはすべての条件でスムーズに実行されます。再度、感謝します! – hashir

3

これはpl/sqlソリューションであり、あなたの試行より簡単です。コメントで説明のビット:

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;  

これは効率的な解決策ではないことに注意してください、どちらの方法は、私はこれを実装するだろうが、私はあなたの手順を構築するためのいくつかのヒントを与えるのに十分明らかであると思います。

これは、SQLソリューションのようになります。

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) 

ここでは、「トリッキー」の部分は値2000, 3000, ... 25000のリストを生成するために使用される内部クエリ、次のとおりです。

ここ
select (level +1) * 1000 as sal 
from dual 
connect by (level +1) * 1000 <= 25000 

私はNOT INを使用これは完璧な選択ではないかもしれませんが、私はそれが全く自明であることを願っています。論理は "のようなもので、ではなく、の給与リスト"である2000のすべての値をリストします。

+0

Aleksejに上記のソリューションをお寄せいただきありがとうございました。また、応答時間も圧倒的でした。私はあなたが提供した最初のソリューションはかなりカジュアルなアプローチであり、もう1つはよりスマートなアプローチであると付け加えたいと思います。しかし、どちらも非常に効率的に仕事をします – hashir