首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在应用限制子句之前,组是否按唯一键计算所有组?

在应用限制子句之前,组是否按唯一键计算所有组?
EN

Stack Overflow用户
提问于 2009-04-14 13:47:55
回答 3查看 640关注 0票数 3

如果我在唯一键上使用GROUP BY,并将一个LIMIT子句应用于查询,那么在应用该限制之前,是否会计算所有组?

如果表中有100条记录(每个记录都有唯一的键),那么在应用100之前,是否会在临时表中创建LIMIT记录(用于LIMIT)?

我需要这个的一个案例研究:

Stack Overflow为例。

您运行的每个查询都显示了一个问题列表,还显示了问这个问题的用户以及他拥有的徽章的数量。

所以,当用户<->问题是一对一时,用户<->徽章是有很多的。

在一个查询(而不是一个关于问题的查询,另一个对用户的查询,然后组合结果)中进行查询的唯一方法是将查询按主键(question_id)和join+group_concat分组到user_badges表。

同样适用于问题标签.

代码语言:javascript
复制
Code example:
Table Questions:
question_id  (int)(pk)|   question_body(varchar)


Table tag-question:
question-id (int) | tag_id (int)


SELECT:

SELECT quesuestions.question_id,
       questions.question_body,
       GROUP-CONCAT(tag_id,' ') AS 'tags-ids'
FROM
       questions
   JOIN
       tag_question
   ON
       questions.question_id=tag-question.question-id
GROUP BY
       questions.question-id
LIMIT 15
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-04-14 14:33:19

LIMIT确实是在GROUP BY之后应用的。

是否创建临时表取决于如何构建索引。

如果在分组字段上有一个索引,并且不按聚合结果排序,那么将应用一个INDEX SCAN FOR GROUP BY,然后对每个聚合进行动态计数。

这意味着,如果您不选择一个聚合由于LIMIT,它将永远不会被计算。

但是,如果你按一个集合排序,那么,当然,所有这些都需要在排序之前进行计算。

这就是为什么首先计算它们,然后应用filesort

更新:

至于您的查询,请看EXPLAIN EXTENDED对它说了什么。

最有可能的是,question_id是表的PRIMARY KEY,而且很可能,它将在扫描中使用。

这意味着不会应用filesort,而联接本身也不会在15'th行之后发生。

若要确保,请按以下方式重写查询:

代码语言:javascript
复制
SELECT question_id,
       question_body,
       (
       SELECT  GROUP_CONCAT(tag_id, ' ')
       FROM    tag_question t
       WHERE   t.question_id = q.question_id
       )
FROM   questions q
ORDER BY
       question_id
LIMIT 15

  • 第一,它更易读,
  • ,第二,它更高效,第三,它将返回甚至没有标签的问题(您当前的查询没有)。
票数 1
EN

Stack Overflow用户

发布于 2009-04-14 13:50:11

是的,查询执行的顺序是:

  • FROM
  • WHERE
  • GROUP
  • HAVING
  • SORT
  • SELECT
  • LIMIT

极限是计算的最后一件事,所以你的分组会很好。

现在,看看您重新措辞的问题,那么您不是每组只有一行,而是很多:在堆栈溢出的情况下,每一行只有一个用户,但是有许多标记。

代码语言:javascript
复制
(uid, badge_id, etc.)
(1, 2, ...)
(1, 3, ...)
(1, 12, ...)

所有这些都将被组合在一起。

为了避免全表扫描,您所需要的只是索引。此外,如果您需要求和,例如,您无法避免全面扫描。

编辑:

您需要这样的东西(看看WHERE子句):

代码语言:javascript
复制
SELECT
  quesuestions.question_id,
  questions.question_body,
  GROUP_CONCAT(tag_id,' ') AS 'tags_ids'
FROM
  questions q1
  JOIN tag_question tq
    ON q1.question_id = tq.question-id
WHERE
  q1.question_id IN (
    SELECT
      tq2.question_id
    FROM
      tag_question tq2
        ON q2.question_id = tq2.question_id
      JOIN tag t
        tq2.tag_id = t.tag_id
    WHERE
      t.name = 'the-misterious-tag'
  )
GROUP BY
  q1.question_id
LIMIT 15
票数 4
EN

Stack Overflow用户

发布于 2009-04-14 14:04:20

如果要分组的字段是索引的,则不应该进行完整的表扫描。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/747639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档