プロが教える店舗&オフィスのセキュリティ対策術

Acsess初心者です。クエリでの結合(紐付け?)方法について質問いたします。

2つのテーブルから、各2つずつのフィールドを結合したいのですが、
以下の条件でそれぞれを同値であるようにしたいのです。

テーブルAには、フィールドp、フィールドqが入っています。
テーブルBには、フィールドr、フィールドsが入っています。

※m、nは1以上の整数です
・(フィールドp、フィールドq)=(0、n)のとき、(フィールドr、フィールドs)=(2、n)と同値とする
・(フィールドp、フィールドq)=(m、n)のとき、(フィールドr、フィールドs)=(1、m)と同値とする

上記2点で、2つのテーブルを結合することは可能でしょうか?

A 回答 (6件)

No5です。


「True」という文字列がBooleanで返す「True」とまぎわらしい、という
ことであれば、

Function funcJudge(ByVal fP As Long, ByVal fQ As Long, ByVal fR As Long, ByVal fS As Long) As String
'最初の条件
If fP = 0 And fQ >= 1 And fR = 2 And fS = fQ Then
funcJudge = "同値"
Exit Function
End If
'二番目の条件
If fP >= 1 And fQ >= 1 And fR = 1 And fS = fP Then
funcJudge = "同値"
Exit Function
End If
End Function


のように「同値」でもかまいませんが。
    • good
    • 0
この回答へのお礼

返事が遅くなって申し訳ありません。
これ以上返事を遅らすのもどうかと思い、現在の進捗報告をお礼に代えさせていただきたいと思います。

「同値」を真偽の判定と読み替えて、VBAを使用する、とは目から鱗でした!
また、ご推測の通り、以下の2点が当てはまります。
・ テーブル1とテーブル2の行が1対1で対応しており、それぞれ同じレコード数ある。
・ 「True」と表示されたテーブル2のレコードが「特定したい」というデータに相当する。
(判定の文字列は「True」「同値」いずれでも構いません。
 Booleanで判定させる場合はVBAでの設定が必要、ということでしょうか。
 Booleanでないといけない訳ではありませんが…)

しかし、実際の各テーブルで対応するレコードは、同じ順序に並んでいるわけではないのです。
これには、双方のテーブルで各レコードに割り当てられているIDを結合させれば、解決できそうな気がします。

piroin654さんには多くアドバイスをいただきました。
(各テーブルのレコード数が等しくない場合の対策も知っておきたい、
 などと言うと長引くので置いておきます)
今回長くお付き合いいただいた感謝の意を込めて、今回はBAとさせていただきます。
ありがとうございました。また何かあれば、よろしくお願いいたします。

お礼日時:2012/11/29 11:09

いろいろ想像を巡らしてみました。



理解の仕方が違っているかもしれませんが。
テーブル1とテーブル2の行が1対1で対応していると解釈し、
それぞれ同じレコード数あるというようにした場合。

条件の解釈を、

(フィールドp、フィールドq)=(0、n)のとき、(フィールドr、フィールドs)=(2、n)と同値とする

は、

(フィールドp、フィールドq)=(0、n)かつ、(フィールドr、フィールドs)=(2、n)ならば、
真とする。


また、

(フィールドp、フィールドq)=(m、n)のとき、(フィールドr、フィールドs)=(1、m)と同値とする

は、

(フィールドp、フィールドq)=(m、n)かつ、(フィールドr、フィールドs)=(1、m)ならば、
真とする。


と置き換えます。
そこで、次のコードを標準モジュールに貼り付け、保存してください。


Function funcJudge(ByVal fP As Long, ByVal fQ As Long, ByVal fR As Long, ByVal fS As Long) As String
'最初の条件
If fP = 0 And fQ >= 1 And fR = 2 And fS = fQ Then
funcJudge = "True"
Exit Function
End If
'二番目の条件
If fP >= 1 And fQ >= 1 And fR = 1 And fS = fP Then
funcJudge = "True"
Exit Function
End If
End Function


このコードは条件に合ったときのみ、"True"という文字列を返します。
本来は、関数の戻値をStringではなくBooleanでもいいのですが、
分かりやすくStringとしておきます。
次に、二つのテーブルを1対1で結びつけるオートナンバーを設定し、
それぞれそのフィールドをIDとします。主キーではありません。

クエリを以下のように設定します。

SELECT テーブル2.フィールドr, テーブル2.フィールドs, funcjudge([テーブル1]![フィールドp],[テーブル1]![フィールドq],[テーブル2]![フィールドr],[テーブル2]![フィールドs]) AS 判定
FROM テーブル1 INNER JOIN テーブル2 ON テーブル1.ID = テーブル2.ID;


上記のクエリには、二つの条件の一方に当てはまれば、「判定」という
フィールドに、「True」と表示されます。
「True」と表示されたテーブル2のレコードが「特定したい」という
データに相当するのではと思っているのですが、という解釈が一つです。どうでしょう。

もし、テーブル1とテーブル2のレコード数は同じではなく、
テーブル2はテーブル1よりも多い、あるいは反対の
場合は方法を変えなければなりませんが。
    • good
    • 0

提示された条件から



> ※m、nは1以上の整数です
> ・(フィールドp、フィールドq)=(0、n)のとき、(フィールドr、フィールドs)=(2、n)と同値とする

SELECT * FROM TA INNER JOIN TB ON TA.q=TB.s
WHERE TA.p=0 AND TA.q>=1 AND TB.r=2

> ・(フィールドp、フィールドq)=(m、n)のとき、(フィールドr、フィールドs)=(1、m)と同値とする

SELECT * FROM TA INNER JOIN TB ON TA.p=TB.s
WHERE TA.p>=1 AND TA.q>=1 AND TB.r=1


上記を UNION ALL を使って、

SELECT * FROM TA INNER JOIN TB ON TA.q=TB.s
WHERE TA.p=0 AND TA.q>=1 AND TB.r=2
UNION ALL
SELECT * FROM TA INNER JOIN TB ON TA.p=TB.s
WHERE TA.p>=1 AND TA.q>=1 AND TB.r=1;

もし、重複するものがあって排除するのなら UNION ALL を UNION に変更します。
また、違う書き方すれば

SELECT * FROM TA, TB
WHERE (TA.q=TB.s AND TA.p=0 AND TA.q>=1 AND TB.r=2)
OR (TA.p=TB.s AND TA.p>=1 AND TA.q>=1 AND TB.r=1);

になるかも・・・・


※ 各処理性能はわかりません
    • good
    • 0
この回答へのお礼

30246kikuさん、ご回答ありがとうございました。
また、返事が遅れてしまって申し訳ありませんでした。見よう見まねでSQL構文を組んでおりまして…。

ユニオンクエリ、WHERE以下の複数条件の両方を組み、実行することができました。
今回、各データはIDで結合させているので、重複を排除する必要はありませんでした。
結果、ユニオンクエリは処理に1分以上を要するようで、数秒で済む複数条件の方を取ろうかと思っています。

質問の締め切りは、もうお一方が示されたVBAの処理を試みたあとで行う予定です。
ご協力いただき、本当に助かりました。感謝しております。
また何かあれば、よろしくお願いいたします。

お礼日時:2012/11/27 16:02

失礼しました。

たとえば以下のようなテーブルが
あるとして、


[テーブル1]
フィールドp  フィールドq
5         3
9         0
0         3
6         9
1         9


[テーブル2]
フィールドr  フィールドs
0         3
6         3
1         9
9         0
1         3


どのような結果が必要なのでしょうか。
「結合」、あるいは「つなげる」とは?

この回答への補足

度々ご回答ありがとうございます。
「結合」「つなげる」という言い方は、たとえば
クエリのデザインビューで、テーブル同士のフィールドを結合線でつなげる、
というイメージをもとに使っていました。

しかし、今回「結合」したいのは、各テーブルのフィールド2つの組み合わせなのです。

(その後、テーブル2の別のフィールドtに登録されたデータを今回のクエリに表示させ、
別の選択クエリXで表示させる予定です。
このフィールドtには、別途抽出したいデータも混在しており、
初めに作った選択クエリXでは同時に抽出できなかったためです。
このフィールドtで、今回抽出したいデータを特定するためのデータは、
テーブル1のフィールドr、sにしか存在していません )

以下に、ご提示いただいた表の内容を変えて説明いたします。
テーブル1、2の行ごとに、それぞれ対応しています。
これらが同値であるように設定したい (そして、テーブル2のフィールドtのデータを得たい) のです。
お力添え願えますでしょうか。

[テーブル1]
フィールドp  フィールドq
0         3
0         2
1         3
6         9
2         8


[テーブル2]
フィールドr  フィールドs
2         3
2         2
1         1
1         6
1         2

補足日時:2012/11/21 15:51
    • good
    • 0

すみません。

やはり勘違い。フィールドの設定を間違えていました。
No1は引っ込めます。
    • good
    • 0

勘違いしていたらごめんです。



条件を元に、それぞれのテーブルからクエリを作成し、
それぞれのクエリをユニオンクエリで結合するということ
でいいのでしょうかね。


SELECT IIf([テーブルA]![フィールドp]=0 And [テーブルA]![フィールドq]>=1,2,[テーブルA]![フィールドp]) AS PR, IIf([テーブルA]![フィールドp]=0 And [テーブルA]![フィールドq]>=1,[テーブルA]![フィールドq],[テーブルA]![フィールドq]) AS QS
FROM テーブルA
UNION SELECT IIf([テーブルB]![フィールドr]>=1 And [テーブルB]![フィールドs]>=1,1,[テーブルB]![フィールドr]) AS PR, IIf([テーブルB]![フィールドr]>=1 And [テーブルB]![フィールドs]>=1,[テーブルB]![フィールドr],[テーブルB]![フィールドs]) AS QS
FROM テーブルB;

この回答への補足

ご回答ありがとうございます。
上記内容は取り消されたとのことですが、やりたいことについて補足します。

各テーブルでクエリを作成するとまでは考えていませんでした。
ユニオンクエリでなく、選択クエリで各テーブルを表示し、先の条件でつなげられればいいかな、と…。
(もしかしたら「結合」の使い方が間違っていたかもしれません)

補足日時:2012/11/21 10:23
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す