【问题标题】:How insert AVG in BETWEEN clause?如何在 BETWEEN 子句中插入 AVG?
【发布时间】:2021-01-19 13:02:31
【问题描述】:

Northwind 为例。我想使用 CASE 子句通过比较 units_in_stock 与其 AVG 值并将此值放在多个 BETWEEN 中来创建类别> 条款。这就是我得到的:

    SELECT product_name, unit_price, units_in_stock,
        CASE
            WHEN units_in_stock > (SELECT AVG(units_in_stock) + 10 FROM products) THEN 'many'
            WHEN units_in_stock BETWEEN (SELECT AVG(units_in_stock) - 10 FROM products) AND (SELECT AVG(units_in_stock) + 10 FROM products) THEN 'average'
            ELSE 'low'
        END AS amount
    FROM products
    ORDER BY units_in_stock;

根据 pgAdmin 中的分析工具 AVG(units_in_stock) 计算了 3 次。有没有办法减少计算量?

【问题讨论】:

    标签: postgresql subquery case average window-functions


    【解决方案1】:

    您可以在子查询中使用窗口函数。另外,在第二个WHEN 条件中不需要使用BETWEEN;大于平均值 + 10 的值由第一个分支处理,永远不会到达第二个分支。

    我会这样说:

    SELECT product_name, unit_price, units_in_stock,
        CASE
            WHEN units_in_stock >  AVG(units_in_stock) OVER() + 10 THEN 'many'
            WHEN units_in_stock >= AVG(units_in_stock) OVER() - 10 THEN 'average'
            ELSE 'low'
        END AS amount
    FROM products
    ORDER BY units_in_stock;
    

    我希望数据库能够优化查询,以便只计算一次窗口平均值。如果不是这种情况,另一种方法是先计算子查询中的平均值:

    SELECT product_name, unit_price, units_in_stock,
        CASE
            WHEN units_in_stock >  avg_units_in_stock + 10 THEN 'many'
            WHEN units_in_stock >= avg_units_in_stock - 10 THEN 'average'
            ELSE 'low'
        END AS amount
    FROM (SELECT p.*, AVG(units_in_stock) OVER() avg_units_in_stock FROM products p) p
    ORDER BY units_in_stock;
    

    【讨论】:

    • 谢谢!第一个查询是最好的性能!关于第二个:我认为 SELECT p.* 语句有错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 2018-06-10
    • 2012-06-18
    相关资源
    最近更新 更多