【问题标题】:Mysql Sub Select Query OptimizationMysql子选择查询优化
【发布时间】:2010-01-18 16:24:09
【问题描述】:

我每天都在运行一个查询来编译统计数据 - 但它似乎真的效率低下。这是查询:

SELECT a.id, tstamp, label_id, (SELECT author_id FROM b WHERE b.tid = a.id ORDER BY b.tstamp DESC LIMIT 1) AS author_id
FROM a, b
WHERE (status = '2' OR status = '3') 
AND category != 6
AND a.id = b.tid
AND (b.type = 'C' OR b.type = 'R')
AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
ORDER BY b.tstamp DESC
LIMIT 500

这个查询似乎运行得很慢。为废话命名道歉 - 我被要求不要透露实际的表名。

之所以有子选择,是因为外部选择从表 a 中获取一行,从表 b 中获取一行。但还需要知道表 b 中最新的 author_id,所以我运行一个子选择来返回那个。我不想在 php 循环中运行另一个选择 - 因为这也是低效的。

它工作正常 - 我只需要找到一种更快的方法来获取此数据集。

【问题讨论】:

  • @Matt:您应该尝试提供的答案,投票有帮助并接受解决您问题的答案。如果他们都没有,请考虑编辑您的问题以提供更多信息。

标签: php sql mysql optimization subquery


【解决方案1】:

如果b.tstampb.tid 中是唯一的,请采用 OMG Ponies 的解决方案。

否则你可以试试这个解决方案。它按b.tstamp DESC 对整个结果进行排序,并按author_id 添加排名。外部选择只取rank = 1 所在的行,这是tstampauthor_id 最大的行。

SELECT id, tstamp, label_id, author_id
  FROM (SELECT id,
               tstamp,
               label_id,
               author_id,
               CASE
                 WHEN @author_id != author_id THEN @row_num := 1 
                 ELSE @row_num := @row_num + 1
               END AS rank,
               @author_id := b.author_id
          FROM a,
               b,
               (SELECT @row_num := 0, @author_id := NULL) y
          WHERE a.id = b.tid
          AND (status = '2' OR status = '3') 
          AND category != 6
          AND (b.type = 'C' OR b.type = 'R')
          AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
          ORDER BY b.author_id, b.tstamp DESC
  ) x
 WHERE x.rank = 1
LIMIT 500

我没试过,如果不行请评论。

【讨论】:

    【解决方案2】:

    试试:

      SELECT a.id,
             b.tstamp,
             label_id,
             y.author_id
        FROM TABLE_A a
        JOIN TABLE_B b ON b.tid = a.id
        JOIN (SELECT b.tid,
                     MAX(b.tstamp) 'm_tstamp'
                FROM TABLE_B b
            GROUP BY b.tid) x ON x.tid = a.id
        JOIN (SELECT b.tid,
                     b.author_id,
                     b.tstamp
                FROM TABLE_B b
            GROUP BY b.tid) y ON y.tid = a.id
                             AND y.tstamp = x.m_tstamp
       WHERE status IN ('2', '3')
         AND b.type IN ('C', 'R')
         AND category != 6
         AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
    ORDER BY b.tstamp DESC 
       LIMIT 500
    

    【讨论】:

    • @Peter Lang:谢谢!已更正。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多