2017-07-28 3 views
0

が含まれています。SQL Developerを使用してOracleストアドプロシージャを変更する。再書き込みNOT INですが、サブクエリにはカンマ区切りの文字列(ID)

入力:カンマ区切りのID。 (例: 'P23、P37、P39、P45') 編集:入力が文字列であることに注意してください。ではなく、文字列の配列です。また、文字列は4つ以上のIDにすることもできます。約200にまで上がる可能性があります。

これらの入力IDを持たないテーブルを探してみたいです。

以下は遅すぎます。ちょうど約300行のデータ(表内)ですが、約20秒かかります。だから私は書き直したい。どのように行うかについてのヒントを教えてください。

ID_Arrayは 'P23、P37、P39、P45'です。

SELECT * FROM StudentInfo 
WHERE StudentClass = 'Primary5A' 
AND StudentID NOT IN 
(
    SELECT REGEXP_SUBSTR(ID_Array, '[^,]+', 1, LEVEL) StudentID 
    FROM DUAL 
    CONNECT BY REGEXP_SUBSTR(ID_Array, '[^,]+', 1, LEVEL) IS NOT NULL 
) 
AND Height <= 150; 

すでにご存じの方もいらっしゃいます。次

SELECT REGEXP_SUBSTR(ID_Array, '[^,]+', 1, LEVEL) StudentID 
    FROM DUAL 
    CONNECT BY REGEXP_SUBSTR(ID_Array, '[^,]+', 1, LEVEL) IS NOT NULL 

は4行の表(?テーブルのような構造)にID_Arrayをオンにします:

+-----+ 
| P23 | 
| P37 | 
| P39 | 
| P45 | 
+-----+ 
+2

ハードID: 'AND St​​udentID NOT IN(' P23 '、' P37 '、' P39 '、' P45 ')と高さ<= 150'の場合、どれくらい時間がかかりますか?両方の実行計画は何を示していますか?あなたのステータスは最新ですか? –

+0

テーブルではなく文字列で操作しているので、カンマで区切られた文字列を分割するさまざまな方法にはほとんど違いがありません。私は、アレックスが提案したように、何か間違っていると思います。 – Ben

+0

文字列をハードコードします。実行計画:カーディナリティ:184、コスト:191、_real_データ。それは、StudentInfoの完全なテーブルスキャンを持っています。以下の回答を使用すると、両方の実行計画が非常に低い(コスト:5など)。 – user3454439

答えて

2

あなたID_Arrayはたくさん長く、ここであなたの例よりでなければなりません。私は 'P23、P37、P39、P45'で非常に良いパフォーマンスを得る。

長い文字列の場合、REGEXP_SUBSTRはかなり遅くなることがあります。可能であれば、代わりにLIKEを使用することをお勧めします。これを試してみてください。

SELECT * FROM StudentInfo 
WHERE StudentClass = 'Primary5A' 
AND ','||ID_Array||',' NOT LIKE '%,'||StudentID||',%' 
AND Height <= 150; 
+0

はい、ID_Arrayの方がずっと長くなっています。撮影に要した時間はダビデの答えよりも少し小さいので、あなたの答えを受け入れることにします。ありがとう。 – user3454439

1

正規表現を使用している場合でも、CONNECT BYを使用する必要はありません。あなたはLIKEを使用するか、またはあなたはREGEXP_LIKE()を使用することができます。

SELECT * FROM studentinfo 
WHERE studentclass = 'Primary5A' 
    AND height <= 150 
    AND NOT REGEXP_LIKE(','||id_array||',', ','||studentid||','); 

私はid_arrayは、正規表現パターンそのものとして使用するのに十分に短いではありません推測している(300行?)。それがあった場合には、次の操作を行うことができます。Oracleで

SELECT * FROM studentinfo 
WHERE studentclass = 'Primary5A' 
    AND height <= 150 
    AND NOT REGEXP_LIKE(student_id, '^(' || REPLACE(id_array, ',', '|') || ')$'); 

しかし、正規表現パターンが限られている、私が思うに、512バイトに。

+0

私は実際に代わりに最初のものを手に入れます。 2番目は正規表現が長すぎると不平を言う。ご協力いただきありがとうございます。 – user3454439

+0

はい、Oracleの正規表現は512バイトに制限されています –

関連する問題