【问题标题】:ORA-00934: group function is not allowed here. Issues with WHERE SUM(x) = (SELECT MIN(SUM(x)))ORA-00934: 此处不允许使用组功能。 WHERE SUM(x) = (SELECT MIN(SUM(x))) 的问题
【发布时间】:2019-05-18 11:54:59
【问题描述】:

需要获得付款最少的客户的姓氏和名字。付款有不同的付款方式按付款方式划分的发票付款,因此我需要将具有相同发票编号的付款相加,然后才能确定哪笔付款是最小的付款。付款和客户是由第三个发票链接的不同实体/表格。实体之间的关系是一对多的,如下所示:

Client -----<= Invoice ------<= Payment. 

SELECT c.first_name, c.last_name FROM client c, invoice i
wHERE i.id_client_fk1 = c.id_pk
AND i.num_pk = (SELECT num_invoice_fk1 
                FROM payment 
                WHERE SUM(amount_after_tax) = (SELECT MIN(SUM(amount_after_tax)) 
                                               FROM payment 
                                               GROUP BY num_pk));

客户在发票中使用的PKFK,发票中的PK 在付款中使用为FK

我想使用与代码中完全相同的逻辑,但显然它必须有效。需要比较WHERE SUM(amount_after_tax) = SELECT MIN(SUM(amount_after_tax))

我知道这不在SQL 中(因此我的问题的标题),但这是我可以想出的解释它的逻辑。

 SELECT c.first_name, c.last_name FROM client c, invoice i
 WHERE i.id_client_fk1 = c.id_pk
 AND i.num_pk = (SELECT num_invoice_fk1 FROM payment
                 WHERE amount_after_tax = (SELECT MIN(SUM(amount_after_tax)) 
                 FROM payment
                 GROUP BY num_pk));

此代码在SQL 中运行,但它并没有达到我想要的效果,因为它仅将个人付款与MIN(SUM(amount_after_tax)) 进行比较。假设我一张发票有 3 笔付款。我需要将它们加起来才能与MIN(SUM(amount_after_tax)) 进行比较。也尝试使用 HAVING,但它不起作用。可能是我经验不足。请帮忙

【问题讨论】:

  • MIN(SUM()) 是不允许的。

标签: sql oracle10g aggregate-functions


【解决方案1】:

您应该使用 having 过滤聚合结果(而不是 where)

SELECT c.first_name, c.last_name 
FROM client c, invoice i
WHERE i.id_client_fk1 = c.id_pk
AND i.num_pk = (SELECT
     num_invoice_fk1 
    FROM payment HAVING SUM(amount_after_tax) = 
      (SELECT MIN(amount_after_tax) 
       FROM payment 
       GROUP BY num_pk)
 );

【讨论】:

    【解决方案2】:

    想到窗口函数:

    select c.first_name, c.last_name
    from client c join
         (select i.id_client_fk1, i.num_pk, sum(p.amount_after_tax) as total_amount,
                 row_number() over (order by sum(p.amount_after_tax) asc) as seqnum
          from invoice i join
               payment p
               on p.num_invoice_fk1 = i.num_pk
          group by i.id_client_fk1, i.num_pk
        ) ip
        on i.id_client_fk1 = c.id_pk
    where seqnum = 1;
    

    子查询聚合数据并使用row_number() 枚举结果。然后外部查询引入名称并选择第一行。

    注意事项:

    • 切勿FROM 子句中使用逗号。
    • 始终使用正确、明确、标准 JOIN 语法。
    • 这里的逻辑很简单。只需汇总即可计算总数并取出第一行。

    编辑:

    因为只想要一行,所以也可以使用rownum

    想到窗口函数:

    select c.first_name, c.last_name
    from (select c.first_name, c.last_name,
                 i.id_client_fk1, i.num_pk, 
                 sum(p.amount_after_tax) as total_amount,
          from invoice i join
               payment p
               on p.num_invoice_fk1 = i.num_pk
               client c join
               on i.id_client_fk1 = c.id_pk
          group by i.id_client_fk1, i.num_pk
          order by total_amount asc
        ) ip
    where rownum = 1;
    

    【讨论】:

    • 请原谅我的无知,但你能给我解释一下这段代码吗?中间部分基本看不懂。或者,有一些我可以做的阅读材料吗?它叫什么名字?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多