【问题标题】:How to get aggregates without using a nested sql query如何在不使用嵌套 sql 查询的情况下获取聚合
【发布时间】:2009-12-11 01:51:40
【问题描述】:

我正在从包含备份作业历史记录的 Avamar (Postgresql) 数据库编写自定义报告。我的任务是显示昨晚失败的作业(基于 status_code),并在同一行显示过去 30 天内该客户的成功率(成功的作业/运行的作业总数)。

因此,整体选择只会选择失败的客户端(status_code 不等于 30000,即成功代码)。但是,对于昨晚的每个失败的客户,我还需要知道有多少工作成功,以及过去 30 天内总共启动/计划了多少工作。 (时间段部分比较简单,为了简单起见,我没有把它包含在下面的代码中。)

根据 Hobodave 对 this similar question 的反馈,我尝试在不使用嵌套查询的情况下执行此操作,但我不太能确定。

在下面的查询中,我收到以下错误: column "v_activities_2.client_name" must appear in the GROUP BY clause or be used in an aggregate function

这是我的(损坏的)查询。我知道逻辑是有缺陷的,但我对如何最好地实现这一点一无所知。提前感谢您的任何指导!

select
  split_part(client_name,'.',1) as client_name,
  bunchofothercolumnns,
  round(
    100.0 * (
      ((sum(CASE WHEN status_code=30000 THEN 1 ELSE 0 END))) /
      ((sum(CASE WHEN type='Scheduled Backup' THEN 1 ELSE 0 END))))
    as percent_total
from v_activities_2
  where
    status_code<>30000
  order by client_name

【问题讨论】:

    标签: sql postgresql aggregate


    【解决方案1】:

    如果 SELECT 中有列没有对它们执行聚合函数,则需要定义 GROUP BY:

      SELECT SPLIT_PART(t.client_name, '.', 1) AS client_name,
             SUM(CASE WHEN status_code = 30000 THEN 1 ELSE 0 END) as successes
        FROM v_activities_2
    GROUP BY SPLIT_PART(t.client_name, '.', 1)
    ORDER BY client_name
    

    您希望以下内容如何工作:

          SUM(CASE WHEN status_code = 30000 THEN 1 ELSE 0 END) as successes
     FROM v_activities_2
    WHERE status_code <> 30000
    

    你不能指望计算你排除的行数。

    【讨论】:

    • 这正是我需要做的,这就是为什么我努力让它在单个查询中工作。这根本不可能吗?实现这一点的唯一方法是将一个查询的输出与第二个查询连接起来吗?
    • @Michael:我建议使用子查询/内联视图。如果您必须更改逻辑,则更容易支持。
    【解决方案2】:

    为什么要避免嵌套查询?

    这似乎是最合乎逻辑/最有效的解决方案。

    如果您在没有 sobqueries(仅 group by)的情况下一次性完成此操作,您将以扫描整个表(或连接表)结束 - 这效率不高,因为昨晚只有一些客户端失败。

    总的来说,子查询并没有那么糟糕。

    【讨论】:

      猜你喜欢
      • 2019-01-01
      • 2011-01-09
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-07
      • 2015-12-02
      相关资源
      最近更新 更多