- PR -

VBSで複数DBから取得した値を比較する方法について

1
投稿者投稿内容
ベジータ
会議室デビュー日: 2007/10/29
投稿数: 14
投稿日時: 2007-10-29 15:56
DB1とDB2にADOを使用して値を取得しています。

例えばDBから以下の値を取得した場合
DB1:A,B,C,D
DB2:B,C,D,E

両方に共通する値(B,C,D)の場合は処理1
DB1にだけ存在する値(A)の場合は処理2
DB2にだけ存在する値(E)の場合は処理3

という様な処理をさせたいと考えていますが
配列等でやろうとしても複数のFor文が必要だったりと
中々良い方法が思いつきません。

なるべくFor文を使わずに上記処理を簡潔に行う方法を
思いつく方がいらっしゃいましたらご教授頂けないでしょうか。
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2007-10-29 17:47
引用:

両方に共通する値(B,C,D)の場合は処理1
DB1にだけ存在する値(A)の場合は処理2
DB2にだけ存在する値(E)の場合は処理3



お求めのものは、キーブレイクのアルゴリズムですね。

2つの値源からくる共通のキーに着目して処理を切り替える。
キー値は、どちらに有る場合も、どちらにも無い場合も、どちらか
にはある場合もある。

RDBが一般化する以前は、もっとも基本的なアルゴリズムでした。


サンプルを書きました。
ご参考になりますでしょうか。

値は何らかの理由で値をDBから取得済み
取得方法はいまからでは変更できない
例示された値より類推してDB1とDB2はソート済みである
と仮定し、

VBS環境
という状況に合うと思われる感じで。

もしも、値の取得の方法を変更できるのでしたら、SQLを書き
換えて、 2つのテーブルから混ぜて取得するようにすると、
より読みやすいものにできますね。

コード:
Dim DB1
DB1 = Array("A","B","C","D")
'DB1 = Array("A","B","C","D","F","H")
Dim DB2
DB2 = Array("B","C","D","E")
'DB2 = Array("B","C","D","E","G")

Dim iDB1
iDB1 = 0
Dim iDB2
iDB2 = 0
Dim nDB1Count
nDB1Count = UBound(DB1)
Dim nDB2Count
nDB2Count = UBound(DB2)

Do While iDB1 <= nDB1Count Or iDB2 <= nDB2Count
  WScript.Echo "iDB1=" & iDB1 & " iDB2=" & iDB2
  If iDB1 > nDB1Count Then
    WScript.Echo "DB2にだけ存在 DB1は処理済 処理3 " & "." & "," & DB2(iDB2)
    iDB2 = iDB2 + 1
  ElseIf iDB2 > nDB2Count Then
    WScript.Echo "DB1にだけ存在 DB2は処理済 処理2 " & DB1(iDB1) & "," & "."
    iDB1 = iDB1 + 1
  ElseIf DB1(iDB1) = DB2(iDB2) Then
    WScript.Echo "両方に共通する処理 " & DB1(iDB1) & "," & DB2(iDB2)
    iDB1 = iDB1 + 1
    iDB2 = iDB2 + 1
  ElseIf DB1(iDB1) < DB2(iDB2) Then
    WScript.Echo "DB1にだけ存在 処理2 " & DB1(iDB1) & "," & DB2(iDB2)
    iDB1 = iDB1 + 1
  Else
    WScript.Echo "DB2にだけ存在 処理3 " & DB1(iDB1) & "," & DB2(iDB2)
    iDB2 = iDB2 + 1
  End If
Loop



_________________
たつごろー
codeseek
こみゅぷらす
ベジータ
会議室デビュー日: 2007/10/29
投稿数: 14
投稿日時: 2007-10-29 19:13
ご回答ありがとうございます。

>例示された値より類推してDB1とDB2はソート済みである

詳しくご説明させて頂きますとDB1からは新規作成するファイル名及び
サーバIPアドレス、DB2からは既存に登録されているファイル名及びIPアドレスを
取得致します。

ファイル名とIPアドレスは別テーブルに格納されていて、
\\IPアドレス\ファイル名いう形式でデータを取得致します。

DB1の\\IPアドレス\ファイル名とDB2の\\IPアドレス\ファイル名が一致した場合は
何もせず、一致しない&DB1にのみ存在する場合、\\IPアドレス\ファイル名を作成します。
一致しない&DB2にのみ存在する場合は\\IPアドレス\ファイル名を削除という処理を
行いたいと考えております。

IPアドレスとファイル名をSQLで取得し、FOR文で数文データを取得し
DB1File="\\" & objA("ipaddress") & "\" & objB("file_name")
という形式でDBからの情報を埋め込み、DB1とDB2を比較しています。

今回ですと、配列を2つ宣言し、取得したDB1FileとDB2Fileを配列に入れ込み
ご教授いただいた処理を行う方法になりますでしょうか。

別の所でもほぼ同じ処理(DBに登録してあるプリンタ一覧情報を取得。WindowsのプリンタとFAXからもプリンタ一覧情報を取得して互いを同じ様に比較する)を行う必要がある為、
是非この方式で行えればと考えています。
上総
大ベテラン
会議室デビュー日: 2006/06/22
投稿数: 107
投稿日時: 2007-10-29 19:29
DB1とDB2で直にやりとりが行えるのであれば、SQL3本で済みそうです。
(使用しているDBとバージョンにより使用出来る出来ないがあります。)

1.共通する値BCDを抽出するSQL
SELECT ALL
DB1.B,
DB1.C,
DB1.D
FROM DB1
INNER JOIN DB2
ON DB1.B = DB2.B
AND DB1.C = DB2.C
AND DB1.D = DB2.D

2.DB1だけに存在する値Aを抽出するSQL
SELECT ALL
DB1.A
FROM DB1
LEFT JOIN DB2
ON DB1.B = DB2.B
AND DB1.C = DB2.C
AND DB1.D = DB2.D
WHERE DB2.D IS NULL



DB2の主キー(NOT NULL)項目がNULLの場合は、
DB1にしかデータが存在しません。

3.DB2だけに存在する値Bを抽出するSQL
SELECT ALL
DB2.B
FROM DB1
RIGHT JOIN DB2
ON DB1.B = DB2.B
AND DB1.C = DB2.C
AND DB1.D = DB2.D
WHERE DB1.B IS NULL



DB1の主キー(NOT NULL)項目がNULLの場合は、
DB2にしかデータが存在しません。

上記のSQLを流してレコードセットがEOFになるまで、それぞれの処理を
流せば最も簡潔な気がします。
※1はINTERSECT演算子、2・3はMINUS演算子を使用する方法もあります。
1のSQLは、DB1とDB2が1対1の関係であればALL、1対N若しくはN対Nで
あればDISTINCTが必要になると思います。

プログラムで比較を行う場合は、たつごろーさんが挙げられている
サンプル通りになると思います。
1

スキルアップ/キャリアアップ(JOB@IT)