0

いくつかのフォーラムでユーザーのアクションを記録する多くのテーブルがあり、各ログイベントには日付があります。昨年アクティブではなかったすべてのユーザーを取得するクエリが必要です。次のクエリがあります(作業クエリ):

SELECT *
FROM (questions AS q
    INNER JOIN Answers AS a
    INNER JOIN bestAnswerByPoll AS p
    INNER JOIN answerThumbRank AS t
    INNER JOIN notes AS n
    INNER JOIN interestingQuestion AS i ON q.user_id = a.user_id
    AND a.user_id = p.user_id
    AND p.user_id = t.user_id
    AND t.user_id = n.user_id
    AND n.user_id = i.user_id)
WHERE DATEDIFF(CURDATE(),q.date)>365
    AND DATEDIFF(CURDATE(),a.date)>365
    AND DATEDIFF(CURDATE(),p.date)>365
    AND DATEDIFF(CURDATE(),t.date)>365
    AND DATEDIFF(CURDATE(),n.date)>365
    AND DATEDIFF(CURDATE(),i.date)>365

そのクエリで何をしているのか-userIdに従ってすべてのテーブルを結合し、各日付列を個別にチェックして、1年以上経過しているかどうかを確認します

すべての日付(最新の日付)の間の最大値を見つけて、これだけを現在の日付と比較するなど、もっと簡単にする方法があるかどうか疑問に思っていました

4

2 に答える 2

2

最高のパフォーマンスを得たい場合は、使用できませんgreatest()。代わりに、次のようにします。

SELECT *
FROM questions q
JOIN Answers             a  ON q.user_id = a.user_id
JOIN bestAnswerByPoll    p  ON a.user_id = p.user_id
JOIN answerThumbRank     t  ON p.user_id = t.user_id
JOIN notes               n  ON t.user_id = n.user_id
JOIN interestingQuestion i  ON n.user_id = i.user_id
WHERE q.date > curdate() - interval 1 year
  AND a.date > curdate() - interval 1 year
  AND p.date > curdate() - interval 1 year
  AND t.date > curdate() - interval 1 year
  AND n.date > curdate() - interval 1 year
  AND i.date > curdate() - interval 1 year

datediff()MySQL が日付列の比較でインデックス ルックアップを実行できるようにすることは避けたいと考えています。(user_id, date)ここで、インデックス ルックアップが機能することを確認するには、テーブルごとに複合 (複数列) インデックスを作成する必要があります。

この複合インデックスでは、(user_id)結合を高速化するために最初の部分がユーザーになり、(date)日付の比較を高速化するために 2 番目の部分が使用されます。を上記の列のみ (like only) に置き換える*と、インデックスのみのスキャンを取得できる可能性があり、これは超高速です。SELECT *user_id

UPDATEWITH残念ながら、MySQL はPostgreSQL やその他のデータベースのような一般的なテーブル式の句をサポートしていません。ただし、次のように一般的な式を因数分解できます。

SELECT *
FROM questions q
JOIN Answers             a  ON q.user_id = a.user_id
JOIN bestAnswerByPoll    p  ON a.user_id = p.user_id
JOIN answerThumbRank     t  ON p.user_id = t.user_id
JOIN notes               n  ON t.user_id = n.user_id
JOIN interestingQuestion i  ON n.user_id = i.user_id,
(SELECT curdate() - interval 1 year AS year_ago) x
WHERE q.date > x.year_ago
  AND a.date > x.year_ago
  AND p.date > x.year_ago
  AND t.date > x.year_ago
  AND n.date > x.year_ago
  AND i.date > x.year_ago
于 2013-04-27T19:48:49.387 に答える
1

greatest()MySQL では、次の関数を使用できます。

WHERE DATEDIFF(CURDATE(), greatest(q.date, a.date, p.date, t.date, n.date, i.date)) > 365

これは読みやすさに役立ちます。パフォーマンスには影響しません。

于 2013-04-27T19:24:48.790 に答える