具有group by和having的复杂SQL查询

时间:2009-12-17 11:04:22

标签: sql postgresql

我有桌面订单

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抱怨它需要在表中有一个名为percent的列来根据它来过滤结果。任何帮助表示赞赏。

感谢。

3 个答案:

答案 0 :(得分:2)

将其更改为:

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

由于percent不是实际列,因此您需要为其执行计算以执行过滤。

修改

好的,再看看这个,你至少有两种方法可以写这个:我推荐的第一种方法,就是包含一个子查询(正如有人建议的那样):

选项1

SELECT  vendor As vendor,
        factory As factory,
        [count],
        ROUND(filter_orders / count * 100, 4) as  [percent]
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
    FROM    @orders
    GROUP BY vendor_no,
            factory_no
) AS a
WHERE ROUND(filter_orders / count * 100, 4) > 20

选项2

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(SUM(CASE WHEN fcr_date > completion_date THEN 1 ELSE 0 END) / count(1) * 100, 4) as  [percent]
FROM    @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

答案 1 :(得分:1)

使用外部过滤查询包裹您的查询:

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

答案 2 :(得分:0)

我很确定你不能在使用子句或group by子句时使用别名(比如%)。而且“非常”我的意思是Oracle不会让我在使用/ group by子句时使用别名......不确定其他供应商。