【问题标题】:MySQL subqueriesMySQL 子查询
【发布时间】:2010-05-07 12:52:48
【问题描述】:

我们可以在没有子查询的情况下执行此查询吗?

SELECT login, post_n,

(SELECT SUM(vote) FROM votes WHERE votes.post_n=posts.post_n)AS votes, 
(SELECT COUNT(comments.post_n) FROM comments WHERE comments.post_n=posts.post_n)AS comments_count 

FROM users, posts 
WHERE posts.id=users.id AND (visibility=2 OR visibility=3) 
ORDER BY date DESC LIMIT 0, 15

表格:

用户:id、登录名

帖子:post_n、id、可见性

投票:post_n,投票

id — 用户 id,Users 主表。

【问题讨论】:

  • 可见性属于哪个表?
  • 我已经在一分钟前回复了帖子

标签: mysql optimization subquery


【解决方案1】:

是的,有可能:

SELECT login, post_n,

SUM(vote) as votes,

FROM users 
JOIN posts using(id)
LEFT JOIN votes using(post_n)
WHERE visibility=2 OR visibility=3 
GROUP BY login, post_n

然后将结果展平:

select * from 
(
    SELECT login, post_n,

    SUM(vote) as votes,

    FROM users 
    LEFT JOIN posts using(id)
    LEFT JOIN votes using(post_n)
    WHERE visibility=2 OR visibility=3 
    GROUP BY login, post_n
) as votes_count

然后加入 cmets:

select votes_count.login, votes_count.post_n, votes_count.votes, 

    COUNT(comments.post_n) as comments_count

from 
(
    SELECT login, post_n,

    SUM(vote) as votes,

    FROM users 
    LEFT JOIN posts using(id)
    LEFT JOIN votes using(post_n)
    WHERE visibility=2 OR visibility=3 
    GROUP BY login, post_n
) as votes_count
LEFT JOIN comments using(post_n)
GROUP BY votes_count.login, votes_count.post_n
ORDER BY date DESC LIMIT 0, 15

【讨论】:

  • 它看起来不像有子查询,但它有。见dev.mysql.com/doc/refman/5.0/en/explain.html
  • 这不是子查询(在 3 个表上来回查询乒乓球)。它被称为表派生,表派生更有效。但是如果 MySQL 已经有 CTE,则表派生会更优雅
  • @Maksim:尝试辨别表派生(高效)和子查询(低效)之间的区别
  • 尝试感受一下一流的表派生,下载MSSQL或Postgresql和google CTE(common table expression)。遗憾的是,MySQL 还没有 CTE,因此您必须通过将其括在括号中来从其他查询中提取中间结果,这称为表派生,而不是子查询
  • ohohoh,its doesnt 工作,错误。它真的会更快吗?谢谢帮助
【解决方案2】:

您可以将投票总和和帖子计数存储在“用户”表中,并通过触发器或“更新”查询进行更新。

【讨论】:

    【解决方案3】:

    当我们使用连接或在哪里合并我们的表时,我已经测试了变体和测试变体。

    没有子查询变体更慢,0.0208 秒,并且 mysql 在投票表中仅使用 271 行,但是当我使用连接时,它使用整行。这里没有子查询变体:

    SELECT res.*, COUNT(*) FROM
    (
      SELECT login, posts.post_n, SUM(vote)AS votes
      FROM users, posts, votes
      WHERE users.id=posts.id AND posts.post_n=votes.post_n AND visibility=3
      GROUP BY posts.post_n
    )AS res, comments
    WHERE comments.post_n=res.post_n
    GROUP BY res.post_n
    ORDER BY date DESC
    LIMIT 0, 15
    

    子查询变量只执行了 0.0027 秒,它没有缓存,但在所有测试中都使用索引。

    附言对不起我的英语

    【讨论】:

      猜你喜欢
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2014-10-13
      • 1970-01-01
      相关资源
      最近更新 更多