- - PR -
DataSet内のテーブル比較について
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-12-18 18:06
はじめて投稿させていただきます。
メモリ上に展開したDataSetの2つテーブルで、 比較してあるカラムの値が異なるレコードを抽出して新たにテーブルを作る方法が判らなくて投稿しました。 どなたか判る方、よろしくお願いします。 環境:Windows XP SP2 VisualStadio 2003 C# 背景: あるシステムの状態を定期的に収集してメモリ上に展開したDataSetにテーブルを作成しています。 テーブルのスキーマは、code, word, bit, status となっており、code+word+bitで一意の1レコードを表します。status は状態。 テーブル例 table1 code word bit status 30 1 0 0 30 1 1 0 30 1 2 0 30 1 3 0 ・ ・ ・ table2 code word bit status 30 1 0 1 30 1 1 0 30 1 2 1 30 1 3 0 ・ ・ ここで、前回集めていたtable1と新たに集めたtable2を比較しstatusの違うレコードを抽出し、新たにテーブルを作成したいのですが、レコードを抽出するためのSQL文の発行方法がわかりません。 結果のテーブル(抽出) table3 code word bit status 30 1 0 1 30 1 2 1 DataAdaptを作成して、データソースにDataSetを指定すればいいのかと考えたのですが、OleDbDataAdapter(OleDbCommand)等に接続できそうなにないので、悩んでいます。 ちなみに、1つのDataSetに2種類のテーブルを作成する試験用のコンソールプログラムを 作ってみました。 ここから先に進めてなくず抽出するためのコードが作れません。 サンプルソース ----------------- using System; using System.Data; namespace ConsoleDataSet { class Class1 { [STAThread] static void Main(string[] args) { Class2 data = new Class2(); DataSet ds = new DataSet("WordBits"); DataSet Notify_ds = new DataSet("NotifyWordBits"); data.Create(ds, "WordBits"); // テーブルを作成 data.Create(Notify_ds, "WordBits"); // テーブルを作成 Notify_ds.Tables["WordBits"].Rows[0]["status"] = 1; // 試しに発生したビットを作る Notify_ds.Tables["WordBits"].Rows[3]["status"] = 1; // 試しに発生したビットを作る Notify_ds.Tables["WordBits"].TableName = "NotifyWordBits"; // テーブルの名前を変えて名前の重複をさける ds.Tables.Add(Notify_ds.Tables["NotifyWordBits"].Copy()); // テーブルを1つにする data.Display(ds); Console.Write("Please Return Key!\r\n>"); Console.ReadLine(); } } class Class2 { // テーブルを作成 public void Create(DataSet ds, string TableName) { DataTable dt = ds.Tables.Add(TableName); DataRow myRow; dt.Columns.Add("code", typeof(string)); //局アドレス フィールド dt.Columns.Add("word", typeof(int)); // Word フィールド dt.Columns.Add("bit", typeof(int)); // Bit フィールド dt.Columns.Add("status", typeof(int)); // Status フィールド for(int word = 1; word < 3; word++) { for(int bit = 0; bit < 4; bit++) { myRow = dt.NewRow(); myRow["code"] = 30; // 局アドレス(任意) myRow["word"] = word; // Word myRow["bit"] = bit; // Bit myRow["status"] = 0; // 状態 dt.Rows.Add(myRow); } } } // テーブルの内容を表示 public void Display(DataSet ds) { foreach(DataTable dt in ds.Tables) { Console.WriteLine("--- ワードビット一覧 ---"); Console.WriteLine(ds.DataSetName + ":" + dt.TableName); foreach(DataRow dr in dt.Rows) { foreach(DataColumn dc in dt.Columns) { Console.Write(" " + dc.ColumnName + ":" + dr[dc]); } Console.Write("\r\n"); } Console.Write("\r\n"); } } } } ------------------------- ちなみにMicrosoft Access でテーブルを作り、クエリーで表示したSQL文では、 下記のように書くとうまく抽出できます。 SELECT Notify.code, Notify.word, Notify.bit, Notify.status FROM Notify INNER JOIN WordBits ON (Notify.bit = WordBits.bit) AND (Notify.word = WordBits.word) AND (Notify.code = WordBits.code) WHERE ((Not (Notify.status)=[WordBits].[status])); どなたかご教示していただければ、助かります。 よろしくお願いします。 | ||||||||||||||||
|
投稿日時: 2004-12-20 08:29
こんにちは。
データセットにSQLを発行するということはできなかったと思います。 わたしだったら、Table2を作った後にTable1とTable2にRelationを張ってDatarowクラスのGetChildRowsメソッドを使って一レコードずつ比較していくのかなと思います。 試してないのでなんともいえませんが。 | ||||||||||||||||
|
投稿日時: 2004-12-20 10:31
メモリ上に初期状態のDataTableを維持する必要がなければ、
1つのDataTable上で処理する方法もあるかと思います。 ある時点での状態が登録されているDataTableをベースに収集した情報で DataTableを更新&更新の抽出&更新の確定を繰り返します。 例だとstatusが更新されるこになるかと思いますが、 情報収集&更新が終わった時点で、 DataTable.GetChanges()メソッドで更新情報を抽出する。 次の収集に備えて、 DataTable.AcceptChanges()メソッドで更新を確定する。 _________________ Tips集/Library集を公開 | ||||||||||||||||
|
投稿日時: 2004-12-21 01:43
ノリックさん、Os_さんご返答ありがとうございました。
ノリックさん ご指摘どおり、SQLを発行することは出来ないようですね。残念. ADO.NETを使い始めたばかりだったので、 DataSetとは、仮想のメモリ上に展開されたDBのような認識をしていたため、 SQLが発行できるものと四苦八苦してしまいました。 Relationは、私も考えたのですが、結局、code,word,bitを合成して、 必ず、一意になるカラムを新たに作る必要があったため断念しました。 ちなみに table1.word --- table2.word のリレーションを張ると 一意のレコード通しの突き合わせにならないため、エラーとなります。 なので、[table1].[code+word+bit] --- [table2].[code+word+bit]とする必要がありました。 Os_さん DataTableを更新&更新の抽出&更新という手段もスマートでいい考えですよね。 当初、この手法で進むもうかとしたんですが、DataTableを維持する必要性と、 レコード数が増えた場合に、nレコード×nレコードの比較となり、 効率が下がると考えてこのやり方も断念しました。 で、いろいろ考え込んだ結果、以下の方法で進めることにしました。 1.table1, table2 それぞれをcode,word,bitでソートを行う。 2.for文でそれぞれのレコードを突き合わせる。(比較回数が最小限になる) 3.statusが異なったものをtable3へ追加していく バカ正直なシンプルなやり方ですが、横着(1発コマンドで抽出)せずに このやり方がベストなんでしょうか。 蛇足. 今回、DataSetにこだわったのは、データ転送オブジェクトとして、 差分のDataSet Tableを他のシステムへ飛ばしたかった理由からです。 いろいろアイデアをいただきありがとうございました。 今後ともよろしくお願いします。 | ||||||||||||||||
|
投稿日時: 2004-12-21 08:29
Osです。
確認です。 >当初、この手法で進むもうかとしたんですが、DataTableを維持する必要性と、 >レコード数が増えた場合に、nレコード×nレコードの比較となり、 >効率が下がると考えてこのやり方も断念しました。 取得した結果を比較する為、table1(DataTable)は維持されるんですよね? また、nレコード×nレコードの比較がわからないのですが、 code,word,bitをキーとしてFindメソッドを使うことで、該当レコードを抽出することも 可能ではないですか? また、前の回答にも書きましたが、前回のステップからの更新のみ扱うのであれば、 レコード数の増加もそれほど多くはならないのではないですか? むしろ比較のためにtable1、table2の両方を維持する方が扱うレコード数が多くなりそうですが、 いかがでしょうか? _________________ Tips集/Library集を公開 | ||||||||||||||||
|
投稿日時: 2004-12-21 08:47
Os_さんが既に触れているメソッドですが、 DataSet.GetChanges メソッド () DataTable.GetChanges メソッド () の「解説」に
[ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-12-21 08:48 ] ちょこっと修正。 [ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-12-21 10:38 ] | ||||||||||||||||
|
投稿日時: 2004-12-21 10:41
Os_ さん、ぢゃん♪さん。
返信ありがとうございます。 >nレコード×nレコードの比較がわからないのですが、 >code,word,bitをキーとしてFindメソッドを使うことで、該当レコードを抽出することも >可能ではないですか? nレコード×nレコードの比較という表現は語弊がありました。すいません。 Findメソッドを使うにしても、DataSetがいかに優れたエンジンだとしても 数回の比較がかかると言う意味です。 ソートをかけて、for文で比較するのとどれだけ差があるかと考えるた場合、 nレコード文のFind文を発行するよりは、for文のほうが分があるだろうと考えました。 しかし、昨今のCPU能力からすれば、ほとんど論ずるに足らないのかもしれませんが。。。 (どちらが早いか計測したほうがいいのでしょうけれど。。。) >Os_さんが既に触れているDataSet.GetChanges メソッド ()の「解説」に 最終的にDataSet.GetChangesで取り出せば、確かに一番いい方法かと思いますが、 GetChangesに至るまでには、Find文×n回、何度かのテーブルCopyを行う必要があると 考えました。 最終的には、以下の方法を考えていました。 (1) SQL文(仮にできたとして)で抽出する。 --> 単純に抽出できる。速度?(一番遅いかも) (2) GetChanges --> 抽出するのが楽。オーバヘッドに難? (3) for文 --> シンプルだけど、少々面倒。 単純な抽出方法、なおかつ速度的に一番有利な方法はどれかと 考えた挙げ句(3)ではないかと考えました。 実際に計測をしたわけではなく、感覚的な判断をしてしまってます。 当初、質問をあげていたSQL文の発行とずれた方法論をとってしまい 質問に相談に乗っていただいた方々には申し訳なく思っています。 この機会にDataSetの使い方やレコード更新に関する更新&抽出方法、 また、SQL文が発行できないことが分かったことは、非常に有意義でした。 ありがとうございました。 | ||||||||||||||||
|
投稿日時: 2004-12-21 10:51
新旧比較と差分取り出し(yangさんのFind文実行はこれでしょう)をやってくれるのがGetChagesメソッド、テーブルCopyをやってくれるのがMergeメソッドなのに……。 なぜFind文の実行が必要ですか?
なぜFind文を使いたがるかのかが分からないです。 [ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-12-21 10:54 ] [ メッセージ編集済み 編集者: ぢゃん♪ 編集日時 2004-12-21 11:05 ] |