【问题标题】:Should I try to reduce selected rows in the subqueries?我应该尝试减少子查询中的选定行吗?
【发布时间】:2026-01-30 14:30:01
【问题描述】:

我有这个问题:

SELECT count(1)
FROM qanda question
JOIN qanda answer ON question.Id = answer.related
WHERE answer.related IS NOT NULL
AND answer.author_id = 29
AND question.amount IS NULL
AND date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 YEAR))
AND answer.id not in (
  select post_id
  from votes
  group by post_id
  having sum(value) < 0)

目前该子查询实际上选择了 890 行。我可以通过将这个 (外部查询中的时间框架约束) 也添加到子查询中来将其减少到 43 行:

. . . where  date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 YEAR))

我可以通过在该子查询的WHERE 子句中添加这一行来进一步减少它(仅 9 行)

. . . and table_code = 15

好吧,有些程序员认为:

向内部查询添加 where 子句会减少行数,但只会删除无关紧要的行。

但我自己相信为该内部查询添加一个WHERE 子句会使其更快。好吧,我很困惑,我应该在该内部查询的WHERE 子句中添加这些条件还是无关紧要?

【问题讨论】:

  • 我认为这只有在您进行IN 测试时才有用,因为它可以使用外部表上的索引。使用NOT IN,它必须进行全扫描,因此减小子查询的大小并没有太大区别。
  • 另外,减小NOT IN 中子查询的大小意味着更多 行将匹配NOT IN 条件。
  • 似乎在子查询中添加谓词会更改返回的 post_id 值集,因为将排除行,并且sum(value) 的评估可能会产生不同的结果。这似乎是将影响外部查询返回的行集。是的,如果有合适的索引可用,向子查询添加谓词可能会提高性能,但这并不一定总是如此。似乎缺少的是外部查询应返回哪些行的规范
  • @Barmar 我多次阅读您的第二个查询,但我仍然无法理解您的意思。我只能理解您同意不为该子查询添加WHERE 子句,对吗?
  • @stack 是的,我认为在这种情况下它不会有帮助。我怀疑 spencer7593 是对的,它可能会改变查询的语义。

标签: mysql sql datetime join


【解决方案1】:

这个呢

SELECT count(1)
FROM qanda question
JOIN qanda answer ON question.Id = answer.related
WHERE answer.related IS NOT NULL
AND answer.author_id = 29
AND question.amount IS NULL
AND answer.date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 YEAR))
AND 0 <= (
  select sum(value)
  from votes
  where post_id = answer.id
)

?

当然还有其他方法。

但是 - 您的子查询正在读取整个 votes 表,而您只需要与作者答案相关的那些。因此,您可以使用带有答案的连接来限制子查询的结果集:

AND answer.id not in (
    select v.post_id
    from votes v
    join qanda a on a.id = v.post_id
    where a.author_id = 29
      and a.date_time > unix_timestamp(DATE_SUB(now(), INTERVAL 1 YEAR))
      and a.related IS NOT NULL
    group by v.post_id
    having sum(v.value) < 0
)

【讨论】:

  • 谢谢.. 点赞。只是为什么你认为这个查询比我的更好(这是问题)
  • 因为您的子查询正在读取整个投票表。虽然我的相关子查询只读取相关投票。
  • 您的第二个查询出现此错误:#1054 - Unknown column 'a.post_id' in 'group statement'
  • 好.. 但有一件事,您的第二个查询是否应该作为您的第一个查询的子查询?因为它返回一个post_id,而不是有零个或多个赞成票的答案的数量。
  • No.. 第二个查询是您的子查询的替代品。
最近更新 更多