1

私は現在、次のコードを使用しています。

SELECT at.article_id, art.datetime, Count(at.article_id) AS common_tagged_art
FROM article_tags AS at INNER JOIN articles AS art ON at.article_id = art.article_id
WHERE at.tag_id = 4 OR at.tag_id = 3 OR at.tag_id = 1
GROUP BY at.article_id
ORDER BY common_tagged_art DESC, art.datetime DESC

これにより、必要なほぼ正確な結果セットが返されます。これは次のようになります。

+-----------+---------------------+-------------+
| article_id| datetime            | common_tags |
+-----------+---------------------+-------------+
|     23    | 2012-09-25 15:37:25 |      3      |
+-----------+---------------------+-------------+
|     24    | 2012-09-25 15:37:24 |      3      |
+-----------+---------------------+-------------+
|     27    | 2012-09-25 15:37:23 |      3      |
+-----------+---------------------+-------------+
|     30    | 2012-09-25 15:37:22 |      3      |
+-----------+---------------------+-------------+
|     21    | 2012-09-25 15:37:21 |      3      |
+-----------+---------------------+-------------+

クエリを調整して、article_id 24が返される結果の2行目にあることがわかるようにする必要があります。次に、2行目より下のすべてを返す必要があります。

サブクエリに100行あり、article_id 24が49行目にあることを確認した場合、行50〜100を返すクエリが必要です。これがMySQLで可能かどうか、または元のクエリを前提としてPHP内で実行する方が適しているかどうかはわかりません。

私がこれまでに持っているものは次のように見えますが、サブクエリの後で途方に暮れています。

SELECT article_id, datetime, common_tags
FROM (
  SELECT at.article_id, art.datetime, Count(at.article_id) AS common_tags
  FROM article_tags AS at INNER JOIN articles AS art ON at.article_id = art.article_id
  WHERE at.tag_id IN (4,3,1)
  GROUP BY at.article_id
  ORDER BY common_tags DESC, art.datetime DESC
) at1
//IDENTIFY which row article_id X is on in at1
//GET any row below row X in at1

どの列にも静的な順序がないという事実がなければ、これは問題にはなりません。

何かアドバイスをいただければ幸いです。

ありがとう!

4

2 に答える 2

0

これが非常に効率的であるとは思いません。

SELECT at.article_id
     , art.datetime
     , COUNT(at.article_id) AS common_tagged_art
FROM article_tags AS at 
  INNER JOIN articles AS art 
    ON at.article_id = art.article_id
WHERE at.tag_id IN (4, 3, 1)
  AND at.article_id <> 23                         --- parameter: 23
GROUP BY at.article_id
HAVING (COUNT(at.article_id), art.datetime) <=
       ( SELECT COUNT(at2.article_id), art2.datetime
         FROM article_tags AS at2
           INNER JOIN articles AS art2 
             ON at2.article_id = art2.article_id
         WHERE at2.tag_id IN (4, 3, 1)
           AND at2.article_id = 23                 --- parameter: 23
       )
ORDER BY common_tagged_art DESC
       , art.datetime DESC ;
于 2012-09-25T23:18:25.600 に答える
0

同様の問題に対する答えを探している他の人のために、これをここに投稿します。最終的に一時テーブルを使用する必要がありましたが、これは約半分の時間で高速であることがわかりました。

">"演算子を使用できるように、すべての結果を新しい一時的な自動インクリメントIDで格納する一時テーブルを作成しました。

CREATE TEMPORARY TABLE at_results (
id INTEGER(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
article_id INTEGER(10) NOT NULL,
datetime DATETIME NOT NULL,
common_tags INTEGER NOT NULL)
SELECT at.article_id, art.datetime, Count(at.article_id) AS common_tags
FROM article_tags AS at 
INNER JOIN articles AS art ON at.article_id = art.article_id
WHERE at.tag_id IN (4,3,1)
GROUP BY at.article_id
ORDER BY common_tags DESC, art.datetime DESC;

次に、一時テーブルに必要な記事のIDのみを使用して別の一時テーブルを作成しました。MySQLでは一時テーブルを複数回参照できないことがわかったため、これは別のテーブルにあります。これは既知のバグです。

CREATE TEMPORARY TABLE results_article
SELECT id
FROM at_results
WHERE article_id = 23;

次に、AIIDがターゲットの記事よりも高い記事をプルしました。

SELECT at_results.id,article_id, datetime, common_tags
FROM at_results, at_article
WHERE at_results.id > results_article.id

これは、私が求めていた正確な結果を返します。これが他の誰かに役立つことを願っています。MySQLにそれほど精通しているわけではないので、MySQLを見つけるのに少し時間がかかりました。

ちなみに、これが最も効率的な方法かどうかは完全にはわかりません。私の知る限り、それはかなりきびきびしています。SQLの経験が豊富な人なら、それがすべての状況で正確かどうかを知ることができます。

于 2012-09-27T15:43:42.147 に答える