0

I have many tables that log the users action on some forum, each log event has it's date. I need a query that gives me all the users that wasn't active in during the last year. I have the following query (working query):

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

what i'm doing in that query - joining all the tables according to the userId, and then checking each date column individually to see if it's been more then a year

I was wondering if there is a way to make it simpler, something like finding the max between all dates (the latest date) and compering just this one to the current date

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)将用于更快的日期比较。如果你只用上面提到的列替换*SELECT *的列(like user_idonly),你可能会得到仅索引扫描,这将是超快的。

更新不幸的是,MySQL 不支持WITH像 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

在 MySQL 中,您可以使用以下greatest()功能:

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

这将有助于提高可读性。它不会影响性能。

于 2013-04-27T19:24:48.790 回答