【问题标题】:Complex SQL query with group by and having具有 group by 和具有的复杂 SQL 查询
【发布时间】:2010-01-21 22:25:41
【问题描述】:

我有一个餐桌订单

orders (
id  int unsigned not null,
fcr_date  TIMESTAMP,
completion_date TIMESTAMP,
factory_no  varchar(255),
vendor_no  varchar(255))

请忽略数据类型拼写错误。

我想编写一个 sql 查询来帮助我过滤每个供应商工厂的数据。要获取的数据包括每个供应商工厂的订单数量(一组唯一的 vendor_no、factory_no)、vendor_no、factory_no 以及 fcr_date 大于 completion_date 的订单百分比(因此百分比 = fcr_date 大于完成的订单数量日期/订单数量)。之后,我需要过滤百分比大于 20% 的数据。

我写了以下查询:

SELECT  vendor_no As vendor,
        factory_no As factory,
        COUNT(1) as count,
        SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) as filter_orders,
    ROUND(filter_orders / count * 100, 4) as  percent  
FROM    @orders
GROUP BY vendor_no,
        factory_no
HAVING percent>20

但是 postgresql 抱怨它需要在 table 中有一个名为 percent 的列来根据它过滤结果。任何帮助表示赞赏。

谢谢。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    改成:

    HAVING ROUND(filter_orders / count * 100, 4) > 20

    因为percent 不是一个实际的列,你需要给它计算来执行过滤器。

    编辑

    好的,进一步看,你至少有两种写法:我推荐的一种是第一种,它涉及包装在子查询中(正如有人已经建议的那样):

    选项 1

    选择供应商 作为供应商, 工厂作为工厂, [数数], ROUND(filter_orders / count * 100, 4) as [percent] 从 ( 选择 vendor_no 作为供应商, factory_no 作为工厂, COUNT(1) 作为计数, SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) as filter_orders 来自@orders GROUP BY vendor_no, factory_no ) 作为一个 WHERE ROUND(filter_orders / count * 100, 4) > 20

    选项 2

    选择 vendor_no 作为供应商, factory_no 作为工厂, COUNT(1) 作为计数, SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) 作为 filter_orders, ROUND(SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) / count(1) * 100, 4) as [percent] 来自@orders GROUP BY vendor_no, factory_no HAVING ROUND(SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) / count(1) * 100, 4) > 20

    【讨论】:

    • 嘿.. POSTGRE 希望我让 HAVING 子句中的列出现在 Group BY 中。有什么想法为什么会这样做?
    • 糟糕,是的——我的错;试试我发布的新示例。
    【解决方案2】:

    用外部过滤查询包装您的查询:

    SELECT * FROM (
        SELECT  vendor_no As vendor,
                factory_no As factory,
                COUNT(1) as count,
                SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) as filter_orders,
            ROUND(filter_orders / count * 100, 4) as  percent  
        FROM    @orders
        GROUP BY vendor_no,
                factory_no
    ) x
    WHERE percent>20
    

    【讨论】:

      【解决方案3】:

      我很确定您不能在包含子句或 group by 子句中使用别名(如百分比)。 “漂亮”是指 Oracle 不会让我在有/分组的子句中使用别名......不确定其他供应商。

      【讨论】:

      • 甚至 POSTGRE 都希望我让 HAVING 子句中的列与 GROUP BY.. 中的列相同 :(
      • 你可以在have和group by子句中使用不同的列。你也不能有别名。 SELECT dd.cost_code, dd.cost_loc, dd.cost_type, SUM (dd.item_amount) FROM items dd GROUP BY dd.cost_code, dd.cost_loc, dd.cost_type HAVING SUM (dd.item_amount) > 3
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多