2017-12-19 4 views
0

以下のSQLは、私が解決しようとしている問題を概念的に再現しています。 NOT IN句を渡すにもかかわらず、3つのレコードがすべて返されます。区切り文字列をNOT IN節に渡す

SELECT * FROM (
SELECT 'JACK' AS VALUE FROM DUAL 
UNION 
SELECT 'JOHN' AS VALUE FROM DUAL 
UNION 
SELECT 'BOB' AS VALUE FROM DUAL 
) WHERE VALUE NOT IN (SELECT 'BOB,JOHN' FROM DUAL); 

私はデータセットからレコードを除外する基準として使用する区切り文字列を保持するテーブルを持っています。しかし、私が持っている問題は、返された文字列が区切られた項目に分解されないということです。私は、上記のに変換したい:

SELECT * FROM (
SELECT 'JACK' AS VALUE FROM DUAL 
UNION 
SELECT 'JOHN' AS VALUE FROM DUAL 
UNION 
SELECT 'BOB' AS VALUE FROM DUAL 
) WHERE VALUE NOT IN ('BOB','JOHN'); 
+0

https://asktom.oracle.com/pls/asktom/f?p=100:11::::P11_QUESTION_ID:210612357425 – OldProgrammer

+0

区切られた文字列を保持する表がありますか?どうして?データベースを適切に使用し、文字列を別々に格納した場合、問合せの作成に問題はありません。 –

+1

'' BOB、JOHN''が**単一の文字列値**であるため、3つのレコードがすべて返されます。明らかに「BOB、JOHN」!=「BOB」と「BOB、JOHN」!=「JACK」と「BOB、JOHN」!=「JOHN」。結果は正しいです。問題は、配列やテーブルなど、より適したものではなく、文字列としてコレクションを格納することです。 – APC

答えて

0

あなたはその問題のためREGEXP_SUBSTRを使用することができます。

SELECT * FROM (
SELECT 'JACK' AS VALUE FROM DUAL 
UNION 
SELECT 'JOHN' AS VALUE FROM DUAL 
UNION 
SELECT 'BOB' AS VALUE FROM DUAL 
) 
WHERE VALUE NOT IN (SELECT regexp_substr('BOB,JOHN','[^,]+', 1, LEVEL) FROM dual CONNECT BY regexp_substr('BOB,JOHN', '[^,]+', 1, LEVEL) IS NOT NULL) 
+0

コードのブロックを掲示し、「これを使用する」と言っても、OPのコードの問題の説明と、そのコードが問題を解決する理由(およびその理由)の説明がない限り、最適なヘルプはありません。 – MT0

+0

そして、それはどこで始まり、終わりますか?彼はsubstrが何であるか知っていますか?彼は正規表現が何で、どのように使われているかを知っていますか?彼は何がつながっているかを知っていますか?彼にさらに質問がある場合、彼はそれらに尋ねることができ、私は助けてくれるだろう。しかし、私は彼が必要とするより多くの情報を推測するのは苦労するだろう。 – aLpenbog

1

'BOB,JOHN'は、2つの文字列値のリストではありません、それはちょうど含むようにたまたま1つの文字列値であります文字列にカンマと:

'JACK' = 'BOB,JOHN' 
'JOHN' = 'BOB,JOHN' 
'BOB' = 'BOB,JOHN' 

NOT INフィルタで一致したので、あなたのクエリはすべての行を返します。すべての偽です。

あなたは区切り文字で自分の価値観やリストを囲み、値がこ​​のようなリストのサブ文字列でないかどうかをテストすることができます:あなたは、ユーザー定義のコレクションを使用することができます

SELECT * 
FROM (
    SELECT 'JACK' AS VALUE FROM DUAL UNION ALL 
    SELECT 'JOHN' AS VALUE FROM DUAL UNION ALL 
    SELECT 'BOB' AS VALUE FROM DUAL 
) 
WHERE INSTR(',' || 'BOB,JOHN' || ',', ',' || value || ',') = 0 

または:

CREATE OR REPLACE TYPE stringlist IS TABLE OF VARCHAR2(20); 

そして値がコレクションのメンバーであるかどうかをテストするMEMBER OF演算子を使用:

SELECT * 
FROM (
    SELECT 'JACK' AS VALUE FROM DUAL UNION ALL 
    SELECT 'JOHN' AS VALUE FROM DUAL UNION ALL 
    SELECT 'BOB' AS VALUE FROM DUAL 
) 
WHERE VALUE NOT MEMBER OF StringList('BOB', 'JOHN'); 
関連する問題