2017-01-12 10 views
0

データベース(Oracle)の列にないArrayListに最初に見つかった番号が必要な要件が1つあります。データベースの列に存在しない番号を見つけよう

表1: - > [0,1上記の表から、

enter image description here

私は3つのリスト

List<Integer> lst1 = new ArrayList<Integer>(); 
List<Integer> lst2 = new ArrayList<Integer>(); 
List<Integer> lst3 = new ArrayList<Integer>(); 

LST1を作るために考えています

シナリオは、このようなものです、2,3,4,5,6 ... 1000]

1st2 - > [a0、a1、a2、a3、a4、a5、a6。 ... A1000]

lst3 - > [B0、B1、B2、B3、B4、B5、B6 .... B1000]

リストがシリアル順に約1000の値が含まれている今のところ。

は今、私は範囲]列でlstsを一致させることができますどのように

enter image description here

以下のようにデータベースのテーブルを持っています。 lstsの値がこの表にないことを確認する必要がありますか?

この場合のように、 "lst1"から見ると、テーブルにない最初の利用可能な値は "1"であり、次に利用可能な値は "3"であり、次に5.6 ...である。 同様に "lst2"の最初の欠損値は "a3"

これは何らかの方法がありますか?

+2

私は多くの場合、Javaでの作業よりもシリアル整数を含むテーブルに参加します。このデータをテーブルに入れる可能性はありますか? –

+0

解決策とは別に、テーブルが小さければ、 'select distinct range from tab'クエリを実行し、DBから受け取ったデータからリストをクリーンアップします。 – Ambrish

+0

これが一度しか行われない場合や、パフォーマンスやエレガンスが本当に心配されていない場合、 'lst'を通じたループのブルートフォースメソッドとDBのクエリが機能します。データベーステーブルが大きくなければ、1000のクエリが単純な回答になる可能性があります。 –

答えて

1

以下のクエリは、range_startとrange_endの接頭辞と数値の評価を取得します。実施例の簡略化のため
Iは、以下のクエリはサブクエリとして上記のクエリを使用して、範囲のすべての値を生成する0-5

SELECT lstname, 
     regexp_substr(rangestart, '[^0-9]') AS Prefix, 
     regexp_substr(rangestart, '[0-9]') AS r_start, 
     regexp_substr(rangeend, '[0-9]') AS r_end 
FROM table_1 

LSTNAME |PREFIX |R_START |R_END | 
--------|-------|--------|------| 
Lst1 |  |0  |5  | 
Lst2 |a  |0  |5  | 
Lst3 |b  |0  |5  | 

の範囲を制限しました。
CROSS JOIN LATERALは、Oracle 12c以降のバージョンで動作します。以前のバージョンを使用している場合は、このクエリを書き直す必要があります。ただLEFT欠損値は、この表に上記のクエリをJOINとNULLでない値をフィルタリング見つけるには

SELECT * FROM table_2 

RANGE | 
------| 
3  | 
a0 | 
a1 | 
a5 | 
b3 | 
b4 | 
b5 | 

SELECT lstname, prefix || val AS val 
FROM (
     SELECT lstname, 
       regexp_substr(rangestart, '[^0-9]') AS Prefix, 
       regexp_substr(rangestart, '[0-9]') AS r_start, 
       regexp_substr(rangeend, '[0-9]') AS r_end 
     FROM table_1 
) x 
CROSS JOIN LATERAL (
    SELECT LEVEL - 1 + x.r_start AS val 
    FROM dual 
    CONNECT BY LEVEL <= x.r_end - x.r_start + 1 
) 

LSTNAME |VAL | 
--------|----| 
Lst1 |0 | 
Lst1 |1 | 
Lst1 |2 | 
Lst1 |3 | 
Lst1 |4 | 
Lst1 |5 | 
Lst2 |a0 | 
Lst2 |a1 | 
Lst2 |a2 | 
Lst2 |a3 | 
Lst2 |a4 | 
Lst2 |a5 | 
Lst3 |b0 | 
Lst3 |b1 | 
Lst3 |b2 | 
Lst3 |b3 | 
Lst3 |b4 | 
Lst3 |b5 | 

そして今はtable_2は、次の値が含まれていることを言います。
は、RANGEは、Oracle

SELECT lstname, val 
FROM (
     SELECT lstname, prefix || val AS val 
     FROM (
       SELECT lstname, 
         regexp_substr(rangestart, '[^0-9]') AS Prefix, 
         regexp_substr(rangestart, '[0-9]') AS r_start, 
         regexp_substr(rangeend, '[0-9]') AS r_end 
       FROM table_1 
     ) x 
     CROSS JOIN LATERAL (
      SELECT LEVEL - 1 + x.r_start AS val 
      FROM dual 
      CONNECT BY LEVEL <= x.r_end - x.r_start + 1 
     ) 
) XX 
LEFT JOIN table_2 t2 
ON t2."RANGE" = xx.val 
WHERE t2."RANGE" IS NULL 
ORDER BY 1, 2; 

LSTNAME |VAL | 
--------|----| 
Lst1 |0 | 
Lst1 |1 | 
Lst1 |2 | 
Lst1 |4 | 
Lst1 |5 | 
Lst2 |a2 | 
Lst2 |a3 | 
Lst2 |a4 | 
Lst3 |b0 | 
Lst3 |b1 | 
Lst3 |b2 | 

サブクエリのこのバージョンは、横方向が参加して、Oracleの10で動作するはずエミュレート

の予約語であるので、私は、この例では、列名として引用符で"RANGE"を使用していますのでご注意くださいしかし、私はそれをテストしていません

SELECT lstname, 
    prefix || column_value AS val 
FROM (
     SELECT lstname, 
       regexp_substr(rangestart, '[^0-9]') AS Prefix, 
       regexp_substr(rangestart, '[0-9]') AS r_start, 
       regexp_substr(rangeend, '[0-9]') AS r_end 
     FROM table_1 
) x 
CROSS JOIN table(cast(multiset(
    SELECT LEVEL - 1 + x.r_start AS val 
    FROM dual 
    CONNECT BY LEVEL <= x.r_end - x.r_start + 1 
) as sys.OdciNumberList)) q 
; 
+0

ありがとう、私は12の代わりにOracle 10で作業しているので、 –

+0

テーブル2が同じままであれば解決方法は変わりますが、一度に1つのリストを一致させるだけですテーブル1から1つのリストだけを選択し(テーブル1から2つのリストを削除できるようにします)、テーブル2の欠損値をlst1から探します。 –

+0

Oracle 10の外部結合をエミュレートする – krokodilko

関連する問題