delphiというよりSQL(delphi5に付属のparadox)についての質問です。
tbl_a(id, item1, item2, ..., itemN)
tbl_b(id, itemA, itemB, ..., itemZZ)
(いずれもフィールド数は動的に変わるため不定)
というテーブルを結合したいのですが、
(1)tbl_b.itemAからitemZZのいずれの値も、tbl_a.item1〜.itemNのいずれとも一致しない場合(idのみ一致)
(2)逆にいずれかと一致する場合
にのみ、tbl_a.id=tbl_b.idをキーとして結合を実施する、というのは、条件句に
tbl_b.itemA <> tbl_a.item1
and
tbl_b.itemA <> tbl_a.item2
and
tbl_b.itemA <> tbl_a.item3
と延々と記述しないといけないのでしょうか。
paradoxのSQLは知らないですが、inはだめですか。
これも長くはなりますが少しすっきりします。
tbl_b.itemA not in (tbl_a.item1,tbl_a.item2,・・・tbl_a.itemN)
and tbl_b.itemB not in (tbl_a.item1,tbl_a.item2,・・・tbl_a.itemN)
and tbl_b.itemC not in (tbl_a.item1,tbl_a.item2,・・・tbl_a.itemN)
・
・
・
and tbl_b.itemZ not in (tbl_a.item1,tbl_a.item2,・・・tbl_a.itemN)
delphi初心者さん、ありがとうございます。
フィールドの数が実行時によって異なるので、
tbl_b.itemA not in (tbl_a.の現在の行)
的な記述ができればと思っているのですが、無理でしょうかね。
> (1)tbl_b.itemAからitemZZのいずれの値も、tbl_a.item1〜.itemNのいずれとも一致しない場合(idのみ一致)
> (2)逆にいずれかと一致する場合
> にのみ、tbl_a.id=tbl_b.idをキーとして結合を実施する
(1)と(2)のどちらかに一致した場合って結局全部ってことになりません?
なんか考え方おかしいかな・・・
項目毎に比較しているのに、肝心の項目数が不定では、無理でしょうね。
テーブルの構造を検討した方が良いと思います。
あれ? さん、(1)と(2)は別々の作業です。書き方が悪くてすみません。
HOtaさん 項目数が一定ならばできるということでしょうか。
実は、別のソフトが吐き出すクロス集計の結果に対しての作業ですので、吐き出し側を何とかすればいいかもしれません。
もう解決したでしょうか?
※paradoxは、あまり使わないし、質問者の言う「テーブルを結合」も何を
言いたいのか分かりませんが・・・
質問者は以下について情報を追加されたい。
1)tbl_a(id, item1, item2, ..., itemN)
tbl_b(id, itemA, itemB, ..., itemZZ)
ここで tbl_a、tbl_bでid以外の全フィールドの属性は同じなのか?
(文字と数字が混在してたりしないか?)
2)仮に、
tbl_a(id, item1, item2,item3)
tbl_b(id, itemA, itemB)
のようにフィールド数が分かっている場合は、条件句に
delphi初心者さん 2009/01/08(木) 21:39:05
の方法を記述すれば、望んだ結果が得られるのか?
回答をいただければ、解決策を提示できるかもしれません。
フィールド数が固定か可変かは、問題ではないと思います。
beagleさん、補足させていただきます。
結合は、文字通り、IDをキーにしたjoin操作です。たとえば(1)の場合ですと、tbl_aにもtbl_bにもid以外重複した内容のフィールドが全くない場合、tbl_cとして(id, item1, item2, ..., itemN, ..., itemA, itemB, ..., itemZZ)を生成したい、ということです。
フィールドの属性は同じvarcharです。
in()句にフィールド名を記述するとエラーになります。例えば、select 〜 where tbl_b.itemA not in (var1, var2 ... )とリテラルで展開したら正常に動作しますが、not in (tbl_a.item1, tbl_a.item2 ... )のようにフィールドを記述するとエラーになります。
とりあえず、現在は出力側ソフトのフォーマットを見直している最中です。
よろしくお願いします。
>not in (tbl_a.item1, tbl_a.item2 ... )のようにフィールドを記述するとエラー
そうでしたか。ではもう一つ教えてください。
tbl_b.itemA <> tbl_a.item1 and tbl_b.itemA <> tbl_a.item2
(中略)
and tbl_b.itemA <> tbl_a.itemN
(中略)
tbl_b.itemZZ <> tbl_a.item1 and tbl_b.itemA <> tbl_a.item2
(中略)
and tbl_b.itemZZ <> tbl_a.itemN
という記述を自動的に生成できれば、問題は解決しますか?
beagleさん
記述の自動生成の件ですが、フィールド名にはある程度の規則性がありますので、現在の方向としては「item*が存在しているならば比較を実施」のようにSQLに文を追加していく事はできないか、というのも検討中です。
それができれば問題は解決だと思います。
返答が遅れてすみません。
with query1 do
begin
sql.clear;
sql.add('select * from tbl_a ');
open;
for i := 0 to FieldCount-1 do
begin
Listbox1.items.add(Fields[i].FieldName);
end;
end;
そちらの環境で、この手順でフィールド名が取得できますか?
よければ、たとえば以下のやり方が考えられます。
const
iStartField = 1;
var
tbl_aFNArray, tbl_bFNArray : array of string;
tbl_aFC, tbl_bFC: Integer;
SQLText, wkaText, wkbText : string;
//tbl_aのフィールド名を取得
with query1 do
begin
sql.clear;
sql.add('select * from tbl_a ');
open;
tbl_aFC := FieldCount-1;
SetLength(tbl_aFNArray, tbl_aFC);
for i := 0 to tbl_aFC do
begin
tbl_aFNArray[i] := Fields[i].FieldName;
end;
close;
end;
//tbl_bのフィールド名を取得
with query1 do
begin
sql.clear;
sql.add('select * from tbl_b ');
open;
tbl_bFC := FieldCount-1;
SetLength(tbl_bFNArray, tbl_bFC);
for i := 0 to tbl_bFC do
begin
tbl_bFNArray[i] := Fields[i].FieldName;
end;
close;
end;
//sql文を動的作成
SQLText := '';
for i := iStartField to tbl_aFC do //ゼロからじゃない
begin
wkaText := 'tbl_a.' + tbl_aFNArray[i];
for x := iStartField to tbl_bFC do //ゼロからじゃない
begin
wkbText ;= 'tbl_b.' + tbl_bFNArray[x];
SQLText := SQLText + wkaText + '<>' + wkbText ;
if (i <> tbl_aFC) or (x <> tbl_bFC) then
begin
SQLText := SQLText + 'and';//最後の最後以外は’AND’を付ける。
end;
end;
end;
Memo1.Text := SQLText;//確認
そのままコピペで動くコードを提示したかったのですが、Delphi環境がないので、
タイプミス等あったらすみません。
※ ループの開始(ゼロか1か)と終了(FieldCountかFieldCount-1か)が正しく
ないかもしれません。お仕事だと思うので、十分な確認をお願いします。
この投稿がお役に立てば幸いです。
諸々の事情で返答が遅くなりましたが、皆さん色々とご丁寧にありがとうございました。
beagleさん、力作のコードを提示いただき、ありがとうございました。
訳あって、まだ検証ができておりませんが、近い将来、きっと検証結果についてお知らせいたしますので、もう少しお待ち下さい。
ツイート | ![]() |