【问题标题】:Optimal SQL to perform multiple aggregate functions with different group by fields执行具有不同分组字段的多个聚合函数的最佳 SQL
【发布时间】:2022-01-13 20:52:42
【问题描述】:

为了简化我正在处理的复杂查询,我觉得解决这个问题很关键。

我有下表

id city Item
1 chicago 1
2 chicago 2
3 chicago 1
4 cedar 2
5 cedar 1
6 cedar 2
7 detroit 1

我正在尝试查找按城市和项目分组的行数与仅按每个唯一城市-项目对的项目分组的行数的比率。

所以我想要这样的东西

City Item groupCityItemCount groupItemCount Ratio
chicago 1 2 4 2/4
chicago 2 1 3 1/3
cedar 1 1 4 1/4
cedar 2 2 3 2/3
detroit 1 1 4 1/4

这是我目前的解决方案,但太慢了。

Select city, item, (count(*) / (select count(*) from records t2 where t1.item=t2.item)) AS pen_ratio
From records t1
Group By city, item

也将 where 替换为 groupBy 并拥有,但这也很慢。

Select city, item, (count(*) / (select count(*) from records t2 group by item having t1.item=t2.item)) AS pen_ratio
From records t1
Group By city, item

(注意:我已经从解决方案中删除了 column3 和 column4 以获得更小的代码)

(编辑:xQbert 指出的错字和 马特贝利)

【问题讨论】:

  • 您是否考虑过为城市和/或项目建立索引?
  • groupItemCounts 的“数学”是什么...我想我明白为什么芝加哥项目 1 的计数为 3(因为芝加哥总共有 3 条记录)但为什么会有 4 条呢?
  • dbfiddle.uk/… 是我必须玩的...

标签: sql join group-by postgresql-13


【解决方案1】:

是否因为它在 select 语句中使用子查询分别评估每一行而变慢?它可能作为相关子查询运行。

如果是这种情况,如果您从连接中获取值并从那里开始,它可能会更快 -

Select city, t1.item, (COUNT(t1.item) / MAX(t2.it_count)) AS pen_ratio
from records t1
JOIN (SELECT item, count(item) AS it_count
      FROM records
      group by item) t2
        ON t2.item = t1.item
GROUP BY city, t1.item

更新了一些错误并包含了基于 xQbert 起点的小提琴。我不得不在小提琴中将 CAST 作为浮点数,但您可能不需要 CAST 并根据数据类型在您的查询中使用上述查询。

我相信这符合您原始查询的意图。

https://dbfiddle.uk/?rdbms=postgres_13&fiddle=d77a715175159304b9192a16ad903347

【讨论】:

    【解决方案2】:

    你可以分两部分来处理它。

    首先,像往常一样聚合到您感兴趣的级别。

    然后,使用分析函数计算出分区的小计(项目,在您的情况下)。

    WITH
      aggregate AS
    (
      SELECT
        city,
        item,
        COUNT(*) AS row_count
      FROM
        records
      GROUP BY
        city,
        item
    )
    SELECT
      city,
      item,
      row_count                               AS groupCityItemCount,
      SUM(row_count) OVER (PARTITION BY item) AS groupItemCount
    FROM
      aggregate
    

    从 xQbert 借来的小提琴

    【讨论】:

    • 对这种方法不太了解,因为在我现有的查询中拟合它可能会变得复杂。不过我会尝试并分析准备好的语句。
    猜你喜欢
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多