3

票を落とすつもりですが、これが論理的かどうかを確認する必要があります。

私は3つのテーブルA、B、Cを持っています。BはAとCの間に多多の関係を作るために使用されるテーブルです。しかし、AとCも1対多の関係で直接関係しているということです。

顧客は次の要件を追加しました。

AとCとの内部結合の表Bから情報を取得し、同じクエリでAとCを1対多の関係で関連付けます

何かのようなもの:

代替テキストhttp://img247.imageshack.us/img247/7371/74492374sa4.png

クエリを実行しようとしましたが、常に0行が返されました。お客様は私が要件を達成できると主張していますが、私はそれを疑っています。コメントはありますか?

PS。もっとわかりやすいタイトルはありませんでしたが、何かアイデアはありますか?

更新:rcarのおかげで、場合によっては、学生が受講したすべてのクラスの履歴を保持するために、これが論理的である可能性があります(学生が一度に1つのクラスしか受講できないと仮定します)

更新:連絡先のテーブル、各連絡先の情報を含むテーブル、および関係テーブルがあります。連絡先の情報を取得するには、情報と1対1の関係を築く必要があります。各連絡先には、いいねと名簿を付けることができます。これが、多対多の関係が実装されている理由です。

完全なアイデアは、連絡先の名前と彼の名簿を取得することです。お客様のアイデアが浮かんだので...クエリに問題があります。基本的にはjdecuyperが作成したクエリを使用しようとしていますが、彼が警告しているように、データが返されません。

4

6 に答える 6

5

これは実行可能なシナリオです。1 つのクエリでテーブルを 2 回結合できます。通常は、テーブルに別のエイリアスを割り当てて、物事を整理します。

例えば:

SELECT s.name AS "student name", c1.className AS "student class", c2.className as "class list"
FROM s
JOIN many_to_many mtm ON s.id_student = mtm.id_student
JOIN c c1 ON s.id_class = c1.id_class
JOIN c c2 ON mtm.id_class = c2.id_class

これにより、すべての学生の名前と「ハードコーディングされた」クラスのリストと、many_to_many テーブルのすべてのクラスが表示されます。

とはいえ、このスキーマは論理的に意味がありません。私が収集できることから、学生が複数のクラスを持つことができるようにしたいので、many_to_many テーブルは、学生に関連付けられたクラスを見つけたい場所である必要があります。テーブル s で使用される id_class エントリが many_to_many のエントリと異なる場合 (たとえば、s.id_class がそのテーブルにのみ表示される担任クラスの割り当てを参照し、many_to_many.id_class が単位取得のためのクラスを参照し、担任クラスを除外する場合)、代わりに、c を 2 つのテーブルに分割したほうがよいでしょう。

そうでない場合、1 つのクラスを s テーブルに配線する必要がある理由を理解するのに苦労しています。

編集:これは例を示すために作成されたスキーマであるというあなたのコメントを見ました。他の場合では、これは賢明な方法かもしれません。たとえば、会社の場所を追跡する場合は、Company テーブル、Locations テーブル、Countries テーブルを使用できます。Company テーブルには、会社の本社の国を追跡する国への 1 対多のリンクがありますが、会社の店舗があるすべての場所を追跡する Locations を介した多対多のリンクがあります。

クライアントにとってスキーマが実際に何を表しているかについて実際の情報を提供できれば、この場合にそれが論理的かどうかを判断するのが簡単になるかもしれません。

于 2008-10-23T06:39:31.977 に答える
3

1対多の関係は、多対多で表すことができます。最も簡単なのは、関係のタイプを示すフィールドをそこに追加することです。次に、1つの「現在の」レコードと任意の数の「履歴」レコードを持つことができます。

ちなみに、お客様の「要件」は、与えられたとおりに表現されていましたか?もしそうなら、私は彼らとの関係を再定義することを考えていると思います。彼らは私に彼らが望む「何」(理想的には、ビジネスドメイン言語では彼らの問題は何であるか)を教えてくれ、「方法」を私に任せるべきです。彼らが物事をどのように実装すべきかを正確に知っているなら、私はエディターでソースコードを開いて彼らに任せたいと思うでしょう!

于 2008-10-23T10:07:40.560 に答える
3

おそらくカフェインが不足しているのかもしれませんが、これをしたい正当な理由が思いつきません. あなたが与えた例では、学生、クラス、および2つを関連付けるテーブルがあります。クエリに何をさせたいかを考えると、平易な英語で言えば、確かにstudentテーブルまたはテーブルのいずれかによって駆動される必要がありclassます。すなわち

  • 学生 1245235 が出席しているすべてのクラスを選択します
  • クラス101に出席するすべての学生を選択する

要件をよりよく説明できますか? そうでない場合は、顧客にそれをやめるように伝えてください。生徒とクラス (A と C) の間に直接の関係を持つことは、純粋な狂気のように思えます。それを行うテーブル B が既にあります...

于 2008-10-23T06:40:38.200 に答える
2

s.id_class は、過去に受講したクラスではなく、学生の現在のクラスを示していると思います。

rcar が示す解決策は機能しますが、すべての行で c1.className を繰り返します。

情報を繰り返さず、1 つ少ない結合を使用する代替方法を次に示します。式を使用して、s.id_class を、mtm テーブルを介して一致する現在の c.id_class と比較できます。

SELECT s.name, c.className, (s.id_class = c.id_class) AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
  JOIN c ON (c.id_class = mtm.id_class);

したがって、is_current は 1 つの行では 1 (真) になり、他のすべての行では 0 (偽) になります。CASEまたは、コンストラクトを使用して、より有益なものを出力できます。

SELECT s.name, c.className, 
  CASE WHEN s.id_class = c.id_class THEN 'current' ELSE 'past' END AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
  JOIN c ON (c.id_class = mtm.id_class);
于 2008-10-23T19:20:36.277 に答える
1

意味がないようです。次のようなクエリ:

SELECT * FROM relAC RAC
  INNER JOIN tableA A ON A.id_class = RAC.id_class 
  INNER JOIN tableC C ON C.id_class = RAC.id_class 
    WHERE A.id_class = B.id_class

一連のデータを生成できますが、一貫性がありません。あるいは、これら 3 つのテーブルの内容と関係に関する情報の重要な部分が欠落している可能性があります。

于 2008-10-23T06:37:41.530 に答える
0

個人的には、お客様から次のような要件を聞いたことはありません。

A と C を内部結合しているテーブル B から情報を取得し、同じクエリで A と C を 1 対多の関係で関連付けます。

要件を翻訳したもののようです。顧客が得たい結果として、要件を平易な英語で指定していただけますか?

于 2008-10-23T10:28:25.150 に答える