【问题标题】:SELECT DISTINCT query taking too long SQLSELECT DISTINCT 查询耗时太长的 SQL
【发布时间】:2021-06-28 08:40:11
【问题描述】:

这是我下面的代码,它需要很长时间才能执行。当我添加 SELECT DISTINCT 时,它会变得很长。

我要做的是获得满足这些条件的独特公司,并计算每个公司拥有多少个团队(这由 auth_user u 表中的每个用户提供的 team_id 给出)。

任何帮助都会很棒,我想学习如何进行更好的 SQL 查询。我知道 GROUP BY 是执行此操作的更好方法,但我似乎无法理解。

SELECT DISTINCT u.company_id, c.name, c.company_type, c.office_location, (SELECT (COUNT(DISTINCT u.team_id)) FROM auth_user u WHERE u.company_id = c.id GROUP BY u.company_id) as number_of_teams, s.status, h.auto_renewal
FROM auth_user u, companies_company c, subscriptions_subscription s, hubspot_company h
    WHERE u.company_id = c.id
        AND s.company_id = c.id
        AND h.myagi_id = c.id
ORDER BY u.company_id ASC

【问题讨论】:

  • edit您的问题并添加使用explain (analyze, buffers, format text)生成的execution plan不是只是一个“简单”解释)为formatted text,并确保保留计划的缩进。粘贴文本,然后将``` 放在计划前一行和计划后一行。还请包括所有索引的完整 create index 语句。
  • 今日提示:始终使用现代、明确的JOIN 语法。更容易编写(没有错误),更容易阅读和维护,如果需要更容易转换为外连接! (但是,没有性能差异。)
  • “现代 JOIN 语法”已经超过 30 年了
  • 子查询中不需要 GROUP BY,只要确保它仍然是相关的。
  • 你还需要 SELECT DISTINCT 吗?是否会消除任何重复的行?

标签: sql postgresql select query-optimization distinct


【解决方案1】:

首先重构您的查询以使用 1992 JOIN 语法,而不是您爷爷的逗号连接语法。 (我是爷爷,JOIN 一经推出,我就开始使用它。)

SELECT DISTINCT u.company_id, c.name, c.company_type, c.office_location, 
       count_of_teams_TODO,
       s.status, h.auto_renewal
  FROM auth_user u
  JOIN companies_company c ON u.company_id = c.id
  JOIN subscriptions_subscription s ON  s.company_id = c.id
  JOIN hubspot_company h ON h.myagi_id = c.id
 ORDER BY u.company_id ASC;

那么,我相信每个用户都属于一个团队;即有一个值auth_user.team_id。并且您希望您的结果集显示公司拥有多少个团队。

所以用COUNT(DISTINCT u.team_id) teams 代替我的count_of_teams_TODO 占位符,得到这个。不需要子查询。但是对于聚合函数COUNT(),我们需要GROUP BY。我们希望按公司、状态和自动续订进行分组。

SELECT c.id, company_id, c.name, c.company_type, c.office_location, 
       COUNT(DISTINCT u.team_id) teams,
       s.status, h.auto_renewal
  FROM auth_user u
  JOIN companies_company c ON u.company_id = c.id
  JOIN subscriptions_subscription s ON  s.company_id = c.id
  JOIN hubspot_company h ON h.myagi_id = c.id
 GROUP BY c.id, s.status, h.auto_renewal
 ORDER BY u.company_id ASC;

应该这样做。研究GROUP BY 和聚合函数。您花在更好地学习这些概念上的每一秒都会对您有所帮助。

就性能而言,先让它发挥作用,然后再问另一个问题。用read this before you ask it 标记它。

【讨论】:

  • 2014 年 9 月 25 日 Mysql 5.7.5。以默认的“仅完整分组”发布。你好像是 MySQL 用户,因为你的查询没有考虑到这个设置? (问题是关于 postgresql,默认情况下有这个)
  • 这就是为什么我将 SELECT 中的第一列更改为公司表的主键。该表中的其他列取决于 pk。
  • 好吧,好像是对的……(见:dba.stackexchange.com/questions/158015/…
  • 是的,很好。不过,我不认为包括GROUP BY 中的所有列,而不仅仅是PK,会造成任何麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多