0

3つのテーブルを結合するのは大変です。私は、ニュースレターのリストを取得するために参加したいnewsletter_items、newsletter_fields、およびnewsletter_mailgroupsを持っています。

Newsletter_items には次のフィールドが含まれます。

letter_id, letter_date, receivers, template, status

That can look like

    1, 1234567899, 1,2 (comma separated), standard.html, 1

Newsletter_fields には次のフィールドが含まれます。

    field_uid, field_name, field_content, field_letter_uid

That can look like 

    1, letter_headline, A great headline, 1

ここで、field_letter_uid は、フィールドが属するニュースレターです。

また、newsletter_mailgroups には次のフィールドが含まれます。

mailgroup_id, mailgroup_name, number_of_members

That can look like 

        1, Group1, 233
        2, Group2, 124
        3, Group3, 54

私が望むのは、これらの 3 つのテーブルを組み合わせて、次のようなすべてのニュースレターのリストを取得できるようにすることです。

Letter date | Letter headline | Receivers | Status

2008-01-01 12:00:00 | A great headline | Group1, Group 2 | 1

つまり、SQLクエリで3つのテーブルを結合し、そのプロセスでメールグループテーブルから受信者を選択し、グループ1、グループ2のようにカンマで区切って表示します

これは私が今得たものです

SELECT A.*, B.* FROM newsletter_items A, newsletter_fields B, WHERE B.field_letter_uid = A.letter_id AND field_name = 'letter_headline' AND A.template = '". $template ."'; 

しかし、メールグループをそこに入れる方法がわかりません。

4

3 に答える 3

2

結合を明示的にすることをお勧めします。
クエリのデバッグと、左結合による内部の変更が容易になります。
SQL'89の暗黙的な結合構文を使用する正当な理由は絶対にありません。

SELECT ni.*
       , nf.*
       , group_concat(nm.mailgroup_name) as mailgroups
FROM newsletter_items ni
INNER JOIN newsletter_fields nf 
  ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm  
  ON (find_in_set(nm.mailgroup_id, ni.receivers))
WHERE  
  nf.field_name = 'letter_headline' 
  ni.template = '". $template ."' 
GROUP BY ni.letter_id;

データベースの設計について。
データベースを正規化することをお勧めします。つまり、カンマ区切りのフィールドを別のテーブルに移動します。

だからあなたはテーブルレシーバーを作ります

Receivers
----------
id integer auto_increment primary key
letter_id integer not null foreign key references newsletter_items(letter_id)
value integer not null

次に、フィールドレシーバーをテーブルから削除しますnewsletter_items

次に、クエリは次のように変更されます。

SELECT ni.*
       , group_concat(r.value) as receivers
       , nf.*
       , group_concat(nm.mailgroup_name) as mailgroups

FROM newsletter_items ni
INNER JOIN newsletter_fields nf 
  ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm  
  ON (find_in_set(nm.mailgroup_id, ni.receivers))
LEFT JOIN receiver r ON (r.letter_id = ni.letter_id)
WHERE  
  nf.field_name = 'letter_headline' 
  ni.template = '". $template ."' 
GROUP BY ni.letter_id;

この変更により、クエリも大幅に高速化されます。

于 2011-08-26T07:57:15.527 に答える
1

許可されている場合は、letter_id、receiver_id フィールドを格納できる、newsletter_item_receivers という新しいテーブルを作成してみませんか? このようなフィールドにコンマで区切られた値があるということは、通常、テーブルがないことを意味します:)

編集:

CSV を使用することで、「receiver_id=5 が受信するニュースレターをすべて教えてください」という回答を取得したいときに、あなたの人生は惨めなものになります :)

SO に関する同様の質問に対する適切な回答は次のとおりです。 データベース フィールドのカンマ区切り値

編集2:

テーブルの関係を正しく理解していれば、次のようになります。

SELECT
  a.letter_date,
  b.receiver_id,
  a.status
FROM newsletter_items_receivers b
  LEFT OUTER JOIN newsletter_items a ON (a.letter_id = b.letter_id)
  LEFT OUTER JOIN newsletter_mailgroups m ON (m.mailgroup_id = b.receiver_id)

ノート!ニュースレターの受信者がいない場合、このクエリはニュースレターを返しません。その機能が必要な場合は、次のようなものを試すことができます。

SELECT
  x.letter_date,
  y.mailgroup_name,
  x.status
FROM (
SELECT
  a.letter_date,
  b.receiver_id,
  a.status
FROM newsletter_items a
  LEFT OUTER JOIN newsletter_items_rec b ON (b.letter_id = a.letter_id)) x
  LEFT OUTER JOIN newsletter_mailgroups y ON (y.mailgroup_id = x.receiver_id)

現在、SQL にアクセスできないため、構文エラーが発生した可能性があります (論理エラーではないことを願っています :))。

@Konerakが指摘したように、なぜこのようにしているのかについては、データベースの正規化とそれが重要な理由について読むことをお勧めします。

about.com のこの記事から始めることができます。ちらっと見ただけで、 http: //databases.about.com/od/specificproducts/a/normalization.htm を読んでも問題ないようです。

また、フィールド名を複数のテーブルで同じにするとよいでしょう。たとえば、newsletter_items には letter_id がありますが、newsletter_fields には field_letter_uid があります。ちょっとした考え :)

于 2011-08-26T07:11:55.313 に答える
0

使ってみて

SELECT A.*, B.*, group_concat(C.mailgroup_name SEPARATOR ',') 
FROM newsletter_items A,  newsletter_fields B, newsletter_mailgroups C  
WHERE B.field_letter_uid = A.letter_id 
      AND field_name = 'letter_headline' 
      AND A.template = '". $template ."' 
      and find_in_set(c.mailgroup_id, A.receivers) 
group by A.letter_id;
于 2011-08-26T07:16:54.140 に答える