1

imageimage_dataの2つのテーブルがあり、これが私のimage_dataテーブルの例です。

image_id | slide_id | language_id  | type   |
101      | 1        | 1            | CQ     |
101      | 2        | NULL         | NULL   |
56       | 5        | 1            | TN     |
56       | NULL     | 2            | NULL   |

つまり、基本的に、各画像には異なるオプションがあり、これを実装するための最良の方法を考えています。私はこれを間違った方法で行っていると感じているからです。

これにより、クエリを実行してGROUP_CONCAT()、複数の行の値を1つの連結された文字列に変換できます。

image_id | slide_id | language_id  | type   |
101      | 1,2      | 1            | CQ     |
56       | 5        | 1,2          | TN     |

これは問題ありませんが、現在の方法の問題は、バックエンドシステムで行を更新するのが非常に難しいようです。

ここに画像の説明を入力してください

したがって、クエリを使用すると、データベースを連結してからすべてを1行にまとめているので、データベースに基づいてチェックするクエリを決定できます。しかし、今は次のようになっています。[保存]をクリックして行を更新すると、どちらを更新しますか?同じ画像IDが複数行存在する可能性があるため、正しい画像IDを更新するにはどうすればよいでしょうか。

別のスライドで画像#101をチェックした場合は、そのスライド用に新しい行を作成する必要があります。その後、別のlanguage_idを追加したい場合は、行がNULL値で存在するため、新しい行を追加しないようにし、NULL値を新しい言語IDに置き換える必要があります。

それは本当に複雑に見え、非常に多くの要因があるため、このメソッドを使用することはプログラムするのが非常に困難です。

これを行うための最良の方法は何でしょうか?どんな提案でも本当にありがたいです。

ありがとう!

4

3 に答える 3

2

あなたがする必要があるのは、あなたのテーブルimagesslides/ languages/typesテーブルの間に N:M (多対多) の関係を実装することです。

次のimageようslides考えてslideくださいimages。-- これは N:M の関係です。言語と型についても同様です。

あなたがする必要があるのは、すべてのエンティティimage_data間のオプションを収容するテーブルを取り除き、代わりに 3 つの個別の相互参照テーブルを持つことです。これをモデル化する方法は次のとおりです。


ベース テーブル:

画像(image_id [PK], ...)

スライド(slide_id [PK]、slide_name、...)

言語(language_id [PK]、language_name、...)

タイプ(type_name [PK], ...)

相互参照表:

images_has_slides (image_id [PK]、slide_id [PK])

images_has_languages (image_id [PK]、language_id [PK])

images_has_types (image_id [PK]、type_name [PK])

ER でどのように見えるか:

多対多 ER ダイアグラム

このタイプの設計では、1 つの場所に 1 つのファクトNULLしかないため、値を処理したり、更新する行を見つけたりする必要はありません。すべてのオプションを取得するには、次のようにする必要があります。GROUP_CONCAT()

SELECT
    a.*,
    GROUP_CONCAT(c.slide_name) AS slides,
    GROUP_CONCAT(e.language_name) AS languages,
    GROUP_CONCAT(f.type_name) AS types
FROM
    images a
LEFT JOIN
    images_has_slides b ON a.image_id = b.image_id
LEFT JOIN
    slides c ON b.slide_id = c.slide_id
LEFT JOIN
    images_has_languages d ON a.image_id = d.image_id
LEFT JOIN
    languages e ON d.language_id = e.language_id
LEFT JOIN
    images_has_types f ON a.image_id = f.image_id
GROUP BY
    a.image_id

次に、画像オプションを更新するには、相互参照テーブルでINSERTandを使用します。DELETE

画像に 2 つの言語を追加したいとします。

INSERT INTO images_has_languages (image_id, language_id) 
VALUES (101, 4), (101, 5);

上記のクエリは、 の ID を持つ言語を の ID を持つ画像に追加45ます101

オプションを削除するには (フォームのチェックを外す) - 画像から 2 つのスライドを削除したいとします。

DELETE FROM images_has_slides WHERE image_id = 101 AND slide_id IN (3,6)

これにより、 の ID を持つ画像から3およびの ID を持つスライドが削除されます。6101

そのため、アプリケーションでは、ユーザーが画像のフォームで値をチェックしていないかチェックしているかに基づいて、挿入/削除クエリを実行する必要があるかどうかを判断できます。

于 2012-07-01T05:01:40.017 に答える
1

スキーマを正規化する必要があります。

  1. あなたはimagesテーブルを持っています:
    CREATE TABLE images (
        image_id   integer,
        image_name varchar(100),
        PRIMARY KEY(image_id)
    );
  1. 各イメージには複数の がありますslides:
    CREATE TABLE slides (
        slide_id   integer,
        image_id   integer,
        slide_name varchar(100),
        PRIMARY KEY(slide_id)
    );

image_typesとについても同様image_languagesです。ロジックを理解していただければ幸いです。そして、必ず適切なFOREIGN KEY制約を追加してください。また、従属テーブルCREATE INDEXの列をオンにすることをお勧めします。image_id

これで、関連するテーブルの各パラメーターごとに 1 行が作成されました。コンテンツの管理は簡単である必要があります。INSERT一部の機能が選択されたときに新しいレコードが作成され、DELETE選択が解除されたときに新しいレコードが作成されます。クエリ (概説された 2 つのテーブルに基づく) は次のようになります。

SELECT i.image_id, i.image_name,
       group_concat(s.slide_id) AS slides
  FROM images i
  LEFT JOIN slides s USING (image_id)
 GROUP BY i.image_id;

いくつかのメモ:

  1. これGROUP BYimage_idPRIMARY KEY_ iamges_
  2. 画像ごとに 1 から開始するslide_id(およびその他も)language_idにしたい場合は、 のように、従属テーブルで 2 フィールドの主キーを使用することができます。type_idPRIMARY KEY (image_id, slide_id)

編集:

多対多の関係についてのメモ。imagescan have manyslidesslide_idcan be shared by manyのように、たまたま 2 セットの関連データがimage_idある場合は、追加のテーブルが必要です。

CREATE TABLE images (
    image_id   integer,
    image_name varchar(100),
    PRIMARY KEY(image_id)
);

CREATE TABLE slides (
    slide_id   integer,
    slide_name varchar(100),
    PRIMARY KEY(slide_id)
);

CREATE TABLE image_slides (
    image_id   integer,
    slide_id   integer,
    create_dt  timestamp,
    PRIMRY KEY (image_id, slide_id)
);
于 2012-07-01T04:43:49.527 に答える
1

テーブルを分割してみましたか?スライドと言語用に別のテーブルを作成し、タイプを画像 ID と同じテーブルに保持する場合は、それを使用してリストを作成できます。次に、外部キーを使用してデータベースを最適化して、パフォーマンスに大きな影響を与えないようにすることができます。

ここで私が意味すること:

画像データ テーブル: image_id と image_type (type は予約語) の 2 つの列。Imageid は主キーであるため、重複はありません (各画像に 1 つのタイプのみが必要であると仮定します)。

イメージ言語テーブル: image id と image_language の 2 つの列。どちらも主キーであるため、同じイメージ ID で言語を複製することはできませんが、イメージ ID には複数の言語を含めることができます。画像 ID の主キーは、画像データ テーブルの主キーにリンクします

画像スライド テーブル: 画像 ID とスライド番号の 2 つの列。上記と同じ (2 つの主キー、関係など)

このようにして、次のようにすべてのデータを取得できます。

SELECT d.image_id, d.image_type, l.image_language, s.slide_number FROM image_data d LEFT JOIN image_language l ON d.image_id = l.image_id LEFT JOIN image_slide s ON s.image_id = s.image_id

左の結合により、十分な言語やスライドがない場合でも、すべてのアイテム ID が常に表示されるようになります。各画像、各言語、および適用される各スライドの行を使用して、一種の「マトリックス」を作成します。たとえば、言語がスペイン語と英語で、スライドが 4 枚ある画像がある場合、各言語のスライドごとに 1 つずつ、合計 8 つのエントリが得られます。

それが必ずしも問題を解決するかどうかはわかりませんが、データベースに少し作業をさせながら、データベースにあるものを正確に制御することが少し簡単になります。

于 2012-07-01T04:52:53.307 に答える