Oracle SQL查询客户姓名、发票总数报FROM关键字缺失求解
问题原因与修正方案
你写的SQL存在多处语法和逻辑错误,对应报错和不符合需求的点如下:
- 直接触发
FROM keyword not found where expected错误的原因:最外层查询缺失SELECT关键字,第一行直接写了聚合函数,SQL语法结构不完整。 - Oracle语法兼容问题:Oracle不支持子查询别名前加
AS,同时列别名包含空格时需要用双引号包裹,不能用单引号(单引号在Oracle中仅用于标识字符串常量)。 - 逻辑缺失:全程没有关联
CUSTOMER表,无法查询到客户的名、姓字段;也没有添加要求的按发票总数降序排序的逻辑。 - 冗余逻辑:统计客户的发票总数不需要关联
LINE(发票行)表——INVOICE表本身已经存储了客户编码和发票号的唯一对应关系,关联LINE表反而会因为单张发票对应多个行项目产生重复数据,你内层子查询写的GROUP BY CUS_CODE, L.INV_NUMBER本质是在给多余关联产生的重复数据去重,属于无意义的性能损耗。
正确可运行的SQL
最简写法不需要嵌套子查询,直接关联客户表和发票表即可,用左连接可以兼容查询没有任何发票的客户(发票数显示为0):
SELECT c.CUS_FNAME AS "First Name", c.CUS_LNAME AS "Last Name", COUNT(i.INV_NUMBER) AS "Total Invoices" FROM CUSTOMER c LEFT JOIN INVOICE i ON c.CUS_CODE = i.CUS_CODE GROUP BY c.CUS_CODE, c.CUS_FNAME, c.CUS_LNAME ORDER BY "Total Invoices" DESC;
如果业务要求仅统计有发票记录的客户,把LEFT JOIN替换成INNER JOIN即可。
基于你原有写法的修正版本
如果要保留你原来的子查询结构,修正后语法如下(不推荐,性能比上面的写法差):
SELECT c.CUS_FNAME AS "First Name", c.CUS_LNAME AS "Last Name", COUNT(il.INV_NUMBER) AS "Total Invoices" FROM CUSTOMER c LEFT JOIN ( SELECT DISTINCT CUS_CODE, I.INV_NUMBER FROM INVOICE I JOIN LINE L ON I.INV_NUMBER = L.INV_NUMBER ) IL ON c.CUS_CODE = IL.CUS_CODE GROUP BY c.CUS_CODE, c.CUS_FNAME, c.CUS_LNAME ORDER BY "Total Invoices" DESC;
注意:Oracle中GROUP BY需要带上所有非聚合的查询字段,这里把CUS_CODE放到GROUP BY里是为了避免不同客户同名同姓导致统计结果错误。
内容的提问来源于stack exchange,提问作者user15866126
相关产品推荐
相关产品推荐

