後のカーソル レコードを先読みすることはできません。また、カーソルを複数回実行するとコストがかかり、とにかく役に立たない可能性があります。
'A'
レコードが常に最初になるようにカーソル内のデータを並べ替えてから、追跡変数を使用'A'
して、現在のname
/のtest_field
組み合わせのレコードがあるかどうかを確認できます。
DECLARE
last_name test.name%TYPE := null;
last_test_field test.test_field%TYPE := null;
has_a BOOLEAN := false;
CURSOR cur IS
SELECT name, test_field, test_field2
FROM test
WHERE name='x'
ORDER BY name, test_field, test_field2;
-- assumes 'A' actually comes first
BEGIN
FOR rec IN cur LOOP
-- reset tracking variables if major values change
IF last_name IS NULL OR last_name != rec.name
OR last_test_field != rec.test_field
THEN
last_name := rec.name;
last_test_field := rec.test_field;
has_a := (rec.test_field2 = 'A');
END IF;
IF has_a THEN
DBMS_OUTPUT.PUT_LINE('name ' || rec.name || ' test_field '
|| rec.test_field || ' test_field2 ' || rec.test_field2
|| ' matched condition');
END IF;
END LOOP;
END;
/
name x test_field 101 test_field2 A matched condition
name x test_field 101 test_field2 ROL matched condition
PL/SQL procedure successfully completed.
より適切なアプローチは、カーソル内のすべてのレコードにフラグを追加し、分析関数を使用して結果セットの「ピーク」を先取りすることです。繰り返しますが、これは実際に値がアルファベット順に最初に来ると仮定しています'A'
。そうでない場合は、実際の値を最初に取得するために関数を微調整する必要があります。
SELECT name, test_field, test_field2,
first_value(test_field2)
over (partition by name, test_field
order by test_field2) as has_a
-- assumes 'A' actually comes first
FROM test;
NAME TEST_FIELD TEST_FIELD HAS_A
---------- ---------- ---------- ----------
x 101 A A
x 101 ROL A
x 102 ROL ROL
x 103 ROL ROL
...またはさらに良いのは、これはターゲット値のアルファベット順に依存せず、より明確な結果が得られるためです。
SELECT name, test_field, test_field2,
MAX(CASE WHEN test_field2 = 'A' THEN 'true' END)
OVER (PARTITION BY name, test_field) AS has_a
FROM test;
NAME TEST_FIELD TEST_FIELD HAS_
---------- ---------- ---------- ----
x 101 ROL true
x 101 A true
x 102 ROL
x 103 ROL
それをカーソルに置くと、次のようになります。
DECLARE
CURSOR cur IS
SELECT name, test_field, test_field2,
MAX(CASE WHEN test_field2 = 'A' THEN 'true' END)
OVER (PARTITION BY name, test_field) AS has_a
FROM test
WHERE name='x'
ORDER BY name, test_field, test_field2 DESC;
-- forcing us to see ROL first, just to show it works
BEGIN
FOR rec IN cur LOOP
IF rec.has_a = 'true' THEN
DBMS_OUTPUT.PUT_LINE('name ' || rec.name || ' test_field '
|| rec.test_field || ' test_field2 ' || rec.test_field2
|| ' matched condition');
END IF;
END LOOP;
END;
/
name x test_field 101 test_field2 ROL matched condition
name x test_field 101 test_field2 A matched condition
PL/SQL procedure successfully completed.
これはまた、ループで最初にレコードを処理することを強制するものではないことに注意してください'A'
。これは、重要である場合とそうでない場合があります。