0

この危険な関数の組み合わせを1つのSQL文で改善する方法を探しました...

コンテキストを説明するために、記事に関するいくつかの情報(article_id、author、...)を含むテーブルと、1つのtag_idを持つarticle_idを含む別のテーブルがあります。記事には複数のタグを含めることができるため、その2番目のテーブルには同じarticle_idと異なるtag_idを持つ2つの行を含めることができます。

私が欲しいもの(この場合は1354)と共通のタグが多い8つの記事のリストを取得するために、次のクエリを作成しました。

SELECT articles.article_id, articles.author, count(articles_tags.article_id) as times
FROM articles
INNER JOIN articles_tags ON (articles.article_id=articles_tags.article_id)
WHERE id_tag IN
    (SELECT article_id FROM articles_tags WHERE article_id=1354)
AND article_id <> 1354
GROUP BY article_id
ORDER BY times DESC
LIMIT 8

それは非常に遅いです...50万の記事の90秒のように。

「時間順」の文を削除することで、ほぼ瞬時に機能しますが、削除すると、最も類似した記事を取得できなくなります。

私に何ができる?

ありがとう!!

4

2 に答える 2

1

副選択に対するクエリは常に時間の無駄です...また、クエリは実際には正確または欠落しているようには見えなかったため、articles_tagsテーブルには2つの列があると仮定しています...1つは実際の記事IDと、それに関連付けられたtag_IDの別のID。

そうは言っても、私は記事1354(あなたが興味を持っているもの)のTAGIDだけを事前にクエリします。これを、同じタグIDで再び記事タグへのデカルト結合として使用します。それから、記事タグエイリアスの2番目のバージョンを取得し、ITの記事IDを取得してから、その一致をカウントします(左結合ではなく、結合を介して)。あなたが持っていたように記事IDにgroupbyを適用し、そしてニヤリと笑うために、記事テーブルに参加して著者を取得します。

さて、注意してください。一部のSQLエンジンでは、すべての非集計フィールドでグループ化する必要があるため、グループに作成者を追加するか(いずれにせよ、記事IDごとに常に同じになります)、MAX(A.author)に変更する必要があります。同じ結果を与える著者として。

(tag_id、article_id)にインデックスを付けると、共通して見つけようとしている「共通」タグからタグが見つかります。1つの記事に10個のタグがあり、別の記事に10個の完全に異なるタグがあり、共通して0になる可能性があります。これにより、他の記事が結果セットに表示されるのを防ぐことができます。

あなたが説明したように、50万の記事を吹き飛ばすことに関連する時間はまだあります。これは、実際のタグエントリの数百万になる可能性があります。

select 
      AT2.article_id,
      A.Author,
      count(*) as Times
   from
      ( select ATG.id_tag
           from articles_tags ATG
           where ATG.Article_ID = 1354
           order by ATG.id_tag ) CommonTags
         JOIN articles_tags AT2
            on CommonTags.ID_Tag = AT2.ID_Tag
            AND AT2.Article_ID <> 1354
            JOIN articles A
               on AT2.Article_ID = A.Article_ID
   group by
      AT2.article_id
   order by
      Times DESC
   limit 8
于 2012-11-24T03:34:10.437 に答える
0

サブクエリなしでこれを実行できるはずであるように思われます。そうすれば、より高速なクエリが得られる可能性があります。

ここで、関心のある記事はそのタグに結合され、さらにこれらのタグを持つ他の記事に結合されます。次に、各記事のタグの数がカウントされ、注文されます。

SELECT a2.article_id, a2.author, COUNT(t2.tag_id) AS times
FROM articles a1 
INNER JOIN articles_tags t1
ON t1.article_id = a1.article_id   -- find tags for staring article
INNER JOIN tags t2
ON t2.tag_id = t1.tag_id           -- find other instances of those tags
AND t2.articles_id <> t1.articles_id
INNER JOIN articles a2
ON a2.articles_id = t2.articles_id -- and the articles where they are used
WHERE a1.article_id = 1354
GROUP BY a2.article_id, a2.author  -- count common tags by articles
ORDER BY times DESC
LIMIT 8

共通のタグ数の下限(例:3)がわかっている場合は、HAVING times > 2前に挿入ORDER BY times DESCするとさらに速度が向上する可能性があります。

于 2012-11-24T22:15:35.630 に答える