1

MySqlとPHPを使用してポーリングシステムにタグ機能を追加しています。ユーザーはタグをクリックして、それぞれのタグを持つすべての投票(別名提案)を一覧表示します。リンクは「/propositions/ tagsed/baseball」のようになります。

mod_rewriteを使用して、「baseball」タグを$tagという変数に割り当てます。

RewriteRule ^propositions/tagged/(.*)$ /propositions/index.php?tag=$1 [L]

ポーリングに関連付けられているタグのタグ名は返されません。どうすればそれらの名前を取得できますか?

以下のクエリは機能しますが、ポーリングに関連付けられたタグのタグ名は返されません。どうすればそれらの名前を取得できますか?また、より効率的に行うことができますか。もう1つ、投票データとともにタグを保存する方がよいでしょうか。しばらく前に、SOが質問のあるテーブル列にタグを含めるようにこれを行うところを見ました。彼らがまだそれをしているのか、それともやったことがあるのか​​わからないが、しばらく前にどこかでそれを見たり読んだりした。

本当にありがとう!

================================================== =====

pb_prop (
  id int(11) NOT NULL auto_increment,
  active tinyint(1) NOT NULL default '1',
  submit_by int(11) NOT NULL,
  total_votes int(11) NOT NULL default '0',
  removed tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Described below as ".PROP_TABLE." p

================================================== =====

pb_prop_tags (
  id int(11) NOT NULL auto_increment,
  prop_id int(11) NOT NULL,
  tag_id int(11) NOT NULL,
  PRIMARY KEY  (id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Described below as ".PROP_TAGS_TABLE." pt

================================================== =====

pb_tags (
  tag_id int(11) NOT NULL auto_increment,
  tag_name varchar(64) NOT NULL,
  PRIMARY KEY  (tag_id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Described below as ".TAGS_TABLE." t

================================================== =====

pb_prop_answers (
  id int(11) NOT NULL auto_increment,
  prop_id int(11) NOT NULL,
  num_votes int(11) NOT NULL default '0',
  PRIMARY KEY  (id),
  KEY poll_id (prop_id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Described below as ".PROP_ANSWERS_TABLE." a

================================================== =====

以下のSQLの動作...改善できますか?元のSQLを投稿してから、selectに特定の列を追加しました...いくつかのワイルドカードを削除しました。また、結果をより適切にフィルタリングするために、WHEREにさらに追加しました。

後に示す元のSQL。

        SELECT
                u.username, u.userid,
                p.*,
                pt.prop_id,
                pt.tag_id,
                t.*,
                (
                    SELECT
                            SUM(num_votes)
                    FROM
                            ".PROP_ANSWERS_TABLE." a
                    WHERE
                            a.prop_id = p.id
                ) AS total_votes,
                (
                    SELECT
                            count(*)
                    FROM
                            ".PROP_ANSWERS_TABLE." a
                    WHERE
                            a.prop_id = p.id
                ) AS total_answers
        FROM
                ".PROP_TABLE." p
        INNER JOIN 
                ".TAGS_TABLE." t
            ON 
                t.tag_name LIKE '%".$tag."%'
        INNER JOIN 
                ".PROP_TAGS_TABLE." pt
            ON 
                pt.tag_id = t.tag_id
        LEFT JOIN
                ".USERS_TABLE." u
            ON
                u.userid = p.submit_by
        WHERE
                pt.tag_id = t.tag_id
            AND
                pt.prop_id = p.id
            AND
                p.removed = 0
            AND
                p.active = 1
            AND
                t.tag_id = pt.tag_id
        ORDER BY
                {$sort} {$dir}

元の投稿されたSQL:

    SELECT
            u.username, u.userid,
            p.*,
            pt.*,
            (
                SELECT
                        SUM(num_votes)
                FROM
                        ".PROP_ANSWERS_TABLE." a
                WHERE
                        a.prop_id = p.id
            ) AS total_votes,
            (
                SELECT
                        count(*)
                FROM
                        ".PROP_ANSWERS_TABLE." a
                WHERE
                        a.prop_id = p.id
            ) AS total_answers
    FROM
            ".PROP_TABLE." p
    INNER JOIN 
            ".PROP_TAGS_TABLE." pt
            ON 
            pt.tag_id = p.id
    INNER JOIN 
            ".TAGS_TABLE." t
            ON 
            t.tag_name LIKE '%".$tag."%'
    LEFT JOIN
            ".USERS_TABLE." u
            ON
            u.userid = p.submit_by
    WHERE
            p.removed = 0
        AND
            p.active = 1
        AND
            t.tag_id = pt.tag_id
    ORDER BY
            {$sort} {$dir}
4

2 に答える 2

0

EXPLAIN を使用して、パフォーマンスと、mysql のパフォーマンス分析に関してどのインデックスが使用されているかを確認します。 http://dev.mysql.com/doc/refman/5.0/en/explain.html

EXPLAIN の結果を解釈する方法については、こちらをご覧ください: http://dev.mysql.com/doc/refman/5.0/en/explain-output.html 次のようなことは避けてください:

  • 可能なキーは「null」です
  • タイプ列は「ALL」を示します
  • 追加の列には、「ファイルソートを使用」または「一時を使用」が表示されます

「一時的な使用」または「ファイルソートの使用」は、多くの場合、クエリの最後に追加の SORT BY ステートメントの結果であることに気付きました。

すべての結合にインデックスが使用されていることを確認します。並べ替え方向が使用されているインデックスの並べ替え方向を反映していない場合、SORT BY を削除するとプロセスが高速化される場合もあります。ただし、コードまたは mysql で (小さい?) 結果セットをソートする方が速いかどうかを確認する必要があります。

于 2012-10-16T13:31:11.213 に答える
0

サブクエリで使用されるテーブルに対して結合し、メインの選択で集計関数を使用するだけで、サブクエリなしでこれを行うことができると思います。それに合わせて、適切な (そしておそらくかなり長い!) GROUP BY 句が必要です。

このようなもの(間違いなくタイプミスがあります)

SELECT u.username, u.userid,
    p.*,
    pt.*,
    SUM(pat.num_votes) AS calc_total_votes,
    COUNT(pat.num_votes) AS calc_total_answers
FROM ".PROP_TABLE." p
INNER JOIN ".PROP_TAGS_TABLE." pt ON pt.tag_id = p.id
INNER JOIN  ".TAGS_TABLE." t ON t.tag_id = pt.tag_id AND t.tag_name LIKE '%".$tag."%'
LEFT JOIN ".PROP_ANSWERS_TABLE." pat ON pat.prop_id = p.id
LEFT JOIN ".USERS_TABLE." u ON u.userid = p.submit_by
WHERE p.removed = 0
AND p.active = 1
GROUP BY u.username, u.userid, p.id, p.active, p.submit_by, p.total_votes , p.removed, pt.id, pt.prop_id, pt.tag_id
ORDER BY {$sort} {$dir}

更新された SQL に基づいて、以下の修正された SQL。これは、行ごとのサブセレクトよりも効率的なサブセレクトに対して JOIN を実行しています。

SELECT u.username, u.userid, p.*, pt.prop_id, pt.tag_id, t.*, Sub1.total_votes, Sub1.total_answers
FROM ".PROP_TABLE." p
INNER JOIN ".PROP_TAGS_TABLE." pt ON pt.prop_id = p.id
INNER JOIN ".TAGS_TABLE." t ON pt.tag_id = t.tag_id
LEFT OUTER JOIN (SELECT prop_id, SUM(num_votes) AS total_votes, count(*) AS total_answers
FROM ".PROP_ANSWERS_TABLE." 
GROUP BY prop_id ) AS Sub1 ON p.id = Sub1.prop_id
LEFT OUTER JOIN ".USERS_TABLE." u ON u.userid = p.submit_by
WHERE t.tag_name LIKE '%".$tag."%'
AND p.removed = 0
AND p.active = 1
ORDER BY {$sort} {$dir}

ただし、この選択は全体的なグループ化だけで実行でき、サブ選択は必要ありません。

于 2012-10-16T11:43:44.920 に答える