2012-03-03 4 views
1

SOサイトに行きましょう。それは質問があり、質問にはそのタグがあります。私の質問は、質問とそのタグを表示する最良の方法は何ですか。彼らはdiffirentテーブルにいるとしましょう。質問とそのタグにSELECT JOINを使用できますか?

SELECT * FROM questions RIGHT JOIN tags ON questions.id = tags.question_id

しかし、1以上のタグがありますので、どのように我々はそれらを一緒に表示していましたか?または、2つのSELECTを作成するだけですか?なぜなら、1ページに1つ以上の質問を表示するので、多くのリソースが必要になるからです。

+0

あなたのタグテーブルは、質問テーブルとタグテーブルの間に多対多ですか? – nnichols

答えて

1

はまずSO right joinが必要とされていないので、あなたは私はあなたが何を考えてやりたい場合は、それが実際に

あなたが言うように、より多くがあることができます... left outer joinをする必要があり、少なくとも1個のタグが必要です1つのタグよりも、orまたはinが必要であるか、複数の行を返すか、文字列集約を行う必要があることを示唆しています。

しかし、それはまだ質問のタグが何であるかを知る必要があるので、非常に良いデータモデルではありません。したがって、tag_id混乱を起こすことなく、postsテーブルにタグを格納するのが最善の方法です。

これは実際にはそうです。

あなたのクエリ(実際に働くだろう)次のようになります。

select Tags 
    from Posts 
where Id = ? 

Tags同じ形式で、あなたはそれらを参照してください、その質問のためのタグの区切りリストである、nvarchar(150)あるご質問の場合それは興味深い!

SOは新しいタグが入力されたときに自動的にタグを作成し、同義語を使用して人々の誤字の訂正を確実にします。したがって、TagsテーブルId | TagNameTagSynonoymsテーブルがあります(wikiサマリーがどこに保存されているか分かりません)。次に、タグの割り当て時に、同義語があるかどうかを確認して、Postsテーブルに書き込む前にそれを修正することができます。

かかわらず、あなたの質問に答えるために、クエリは(も実際に動作します)次のようになります。

select p.*, t.TagName 
    from Posts p 
    join PostTags pt 
    on p.Id = pt.PostId 
    join Tags t 
    on pt.TagId = t.Id 

私はそれがSO実際にないものだとは思わない - PostTagsがあるなぜ私も知りませんまたはTagsテーブルを任意のタグとして使用できる場合、タグが存在するかどうかを確認するために外部キー検索を行う必要はありません。この正規化された方法で関係を保存する必要はありません。同義語システムが確実に機能するように、とTagSynonymsの表に列Tagsが必要です。次に、プライマリキーがIdではなく、TagNameである場合は、ルックアップが1つだけ必要です。

4

nameテーブルがあると仮定すると、GROUP_CONCAT機能を使用します。

SELECT questions.*, 
     GROUP_CONCAT(DISTINCT tags.name -> ORDER BY tags.id SEPARATOR ',') AS `tag_names`, 
     GROUP_CONCAT(DISTINCT tags.id -> ORDER BY tags.id SEPARATOR ',') AS `tag_ids` 
FROM questions 
     RIGHT JOIN tags 
     ON questions.id = tags.question_id 

これは、値がカンマで区切られたであろう2カラムtag_namestag_idsを示すであろう。値を取得すると、それを分解して実際の値を得ることができます。

while($row=mysql_fetch_assoc($result)){ 
     $tag_names = explode("," $row['tag_names']; 
     $tag_ids = explode("," $row['tag_ids']; 
     $tags = array_combine($tag_ids, $tag_names); 
    } 

$tagsそのキーがタグIDと値がタグ名である関連した配列となります。

次の式を使用すると、JSONが作成されます。しかし、あなたのタグ名をエスケープする必要が任意の文字(例えば"

Concat('{', GROUP_CONCAT(Concat('"', tags.id, '":"', tags.name, '"') 
       ORDER BY 
       tags.id), '}') AS `tag_o` 

を持っている場合は、それに頼ってはいけない$tags = json_decode($row['tag_o']);

0

でJSONオブジェクトを取得1の下には、あなたの特定の質問のすべてのタグを提供します。

SELECT * FROM `questions` q INNER JOIN `tags` t ON q.id = t.question_id; 
0

これは、タグテーブルがタグと質問の多対多であることを前提としています。

SELECT questions.*, GROUP_CONCAT(CONCAT(tag.id, '::', tag.name)) 
FROM questions 
LEFT JOIN tags 
    ON questions.id = tags.question_id 
LEFT JOIN tag 
    ON tags.tag_id = tag.id 
GROUP BY questions.id 
関連する問題