1

私がやろうとしていることを説明するには、多くの事前情報が必要です。わかりやすくするために、可能な限り一般化しようとしました。単一のクエリで、別のテーブルにリンクされているタグと一致するページのリストを取得したいと考えています。これらのタグはグループになっています。ID の代わりにアイテムのテキスト表現を使用したいと考えていますが、他に何もなければ、tag_id と taggroup_id を取得するために 2 つの事前クエリを実行できます。それを行う必要がないことを望んでいます。

DB スキーマ:

+-----------------------------------+
| taggroups                         |
+------------------+----------------+
| taggroup_id      | group_name     |
+------------------+----------------+
| 1                | fruits         |
+------------------+----------------+

+-----------------------------------------------+
| tags                                          |
+-------------+-----------------+---------------+
| tag_id      | taggroup_id     | tag_name      |
+-------------+-----------------+---------------+
| 1           | 1               | apple         |
| 2           | 1               | orange        |
| 3           | 1               | grape         |
+-------------+-----------------+---------------+

+--------------------------------------+
| pages                                |
+------------------+-------------------+
| page_id          | title             |
+------------------+-------------------+
| 99               | Doctor a day      |
+------------------+-------------------+

+--------------------------------------------------+
| tags_to_pages                                    |
+------------+----------+---------------+----------+
| join_id    | tag_id   | taggroup_id   | page_id  |
+------------+----------+---------------+----------+
| 1          | 1        | 1             | 99       |
| 2          | 2        | 1             | 99       |
+------------+----------+---------------+----------+

テスト クエリ: ここまでできましたが、うまく動作しないようです。

SELECT
    pages.*, tags.tag_name, taggroups.group_name
FROM
    tags_to_pages
    INNER JOIN taggroups as grp ON (
            grp.group_name = 'fruits'
        AND
            tags_to_pages.taggroup_id = grp.taggroup_id
    )
    INNER JOIN tags as val ON (val.tag_name = 'apple' AND tags_to_pages.tag_id = val.tag_id)
    LEFT JOIN pages ON (tags_to_pages.page_id = pages.page_id)

さらに、どのテーブルにインデックスを付ける必要があり、最適化のためにどのインデックスを使用する必要がありますか?

4

1 に答える 1

0

私はこのようにします:

SELECT
    pages.*, tags.tag_name, taggroups.group_name
FROM
    tags_to_pages
    JOIN taggroups AS grp ON grp.taggroup_id = tags_to_pages.taggroup_id
    JOIN tags AS val ON val.taggroup_id = grp.taggroup_id
    JOIN pages ON tags_to_pages.page_id = pages.page_id
WHERE
    grp.group_name='fruits'
    AND val.tag_name = 'apple'

これはあなたが持っているものとそれほど違いはありませんが、結合基準を節に入れJOIN選択基準を節WHEREに入れています。

このクエリを再入力しているときに、taggroup_id であるべきだと思っていた場所で tag_id を使用しているのを見つけたので、変更しましたが、残念ながら、今は再び表示されません。

また、選択基準についても心配します。たまたまリンゴが果物にならなかった場合はどうなるでしょうか。明らかにこの場合であり、実際には:-)ですが、クエリではフルーツ名とグループ名ではなくフルーツ名のみを指定し、データベースをそのままにして、それを自分で整理する必要があると思います。

また、なぜINNER JOINタグ、tags_to_pages、taggroups に を使用し、ページに OUTER JOIN を使用するのですか? 確かにページがない場合は、NULL で半分がいっぱいの 1 行よりも、行が返されない方がよいでしょうか?

id 列のみにインデックスを付けます。

本当に私の2pの価値があります。

編集

www.sqlfiddle.comでこれのデモをセットアップしました。リストのエイリアスを変更すると、元のクエリは正常に機能しました。SELECT上記の私の試みはうまくいきませんでした:-(。エイリアスにも同じ問題があり、エイリアスを修正すると、クエリは同じ行を2回返しました。

として、最初から書き直しました。

SELECT pages.*, tags.tag_name, taggroups.group_name
FROM pages
JOIN tags_to_pages AS ttp ON ttp.page_id = pages.page_id
JOIN tags ON tags.tag_id = ttp.tag_id
JOIN taggroups ON taggroups.taggroup_id = ttp.taggroup_id
WHERE taggroups.group_name = 'fruits' AND tags.tag_name='apple';

そしてそれはうまく動作しますリンク.

このデモをセットアップしていて、なぜテーブルに を保存したのか疑問に思いtaggroup_idました。tags_to_pages私は SQL とデータベースを「独学」で学んでいます (これを翻訳すると、「私は自分のやり方でそれを補い、「うまくいく」ことを行うことに頼り、何が「正しい」かを見つけるために直感を信頼します) が、そうではありません。これはノーマライゼーションの考え方を壊していませんか?tagsとの間の接続は、テーブルの列taggroupsのみを介して定義されるべきではありませんか? おそらく、データベースを本当に理解している誰かがやって来て、私を正してくれるでしょう。taggroup_idtags

最後に、クエリを試行したときに PHPMyAdmin がハングアップした理由がわかりません。幸運を!

于 2013-06-03T22:11:26.230 に答える