SQL查询在Oracle数据库上给出错误

时间:2017-11-15 15:11:29

标签: sql oracle

我正在尝试编写查询以列出帐户以及当前余额,它所属的分支号以及该分支的平均余额超过帐户所属分支的平均余额。< / p>

表名为acmaster,列为acnocurrbalbranchno

记录:

acno currbal branchno
1    1000     2
2    2000     2
3    3000     3
4    2000     3

我期待这样的结果:

acno  currbal  branchno   AVG(currbal)
2     2000      2           1500
3     3000      3           2500 

这是我目前的查询:

select acno,currbal,branchno,AVG(currbal) abal
from acmaster 
group by branchno as bno
having abal < (select currbal from acmaster group by (select branchno from acmaster where branchno=bno));

得到错误:

ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
*Cause:
*Action:
Error at Line: 3 Column: 19

2 个答案:

答案 0 :(得分:3)

正如FoxCy所提到的,您获得的错误的直接原因是您的分组条款中存在as bno。错误消息正试图帮助您:它引用第3行第19列,这是它的开始。 SQL Developer甚至用红色强调它告诉你它是错的,我想其他客户会做类似的事情。

但是您的选择列表中的列也不是聚合的,不在分组中;您无法在定义的同一查询级别中引用abal别名 - 您必须执行having avg(currbal) > ... - 并且如果您为{{1添加了别名而在选择列表中,你也无法引用它。

你的条款虽然没有多大意义;您尝试比较该平均值的子查询将获得多行,并且在其自己的group-by子句中具有无效子查询。在这一点上,重新开始可能更简单......

获得所需结果的简单方法是:

branchno

相同的子查询作为选择列表中的列表达式重复,并在where子句中重复,该子句是混乱的,重复的,难以维护的,并且难以遵循。

稍微好一点的选择是在内联视图中获取平均值一次,然后从中过滤结果:

select a1.acno, a1.currbal, a1.branchno, (
    select avg(a2.currbal)
    from acmaster a2
    where a2.branchno = a1.branchno
    group by a2.branchno
  ) as abal
from acmaster a1
where a1.currbal > (
    select avg(a3.currbal)
    from acmaster a3
    where a3.branchno = a1.branchno
    group by a3.branchno
  );

      ACNO    CURRBAL   BRANCHNO       ABAL
---------- ---------- ---------- ----------
         2       2000          2       1500
         3       3000          3       2500

请注意,您现在可以引用select * from ( select a1.acno, a1.currbal, a1.branchno, ( select avg(a2.currbal) from acmaster a2 where a2.branchno = a1.branchno group by a2.branchno) as abal from acmaster a1 ) where currbal > abal; 别名,因为它在不同级别的查询中用于定义它的位置。

Oracle还具有分析/窗口功能,可以进一步简化,因此您不需要子查询;如果你这样做:

abal

您可以再次看到每个分支对每行的平均值,并可以将其过滤为内联视图:

select a.acno, a.currbal, a.branchno,
  avg(a.currbal) over (partition by a.branchno) as abal
from acmaster a;

      ACNO    CURRBAL   BRANCHNO       ABAL
---------- ---------- ---------- ----------
         1       1000          2       1500
         2       2000          2       1500
         3       3000          3       2500
         4       2000          3       2500

答案 1 :(得分:1)

让我们一次看一行:

1> select acno,currbal,branchno,AVG(currbal) abal
2> from acmaster 
3> group by branchno as bno 
4> having abal < (select currbal from acmaster group by (select branchno from acmaster where branchno=bno));

在第3行,您尝试在group by语句中对branchno as bno进行别名。你不能这样做,至少不是在oracle中。

在第1行,您引用列acnocurrbal而没有任何形式的聚合函数,但它们不存在于第3行的group by子句中。要么添加聚合对每个列起作用,或将它们添加到group by子句

在第4行中,您尝试从第1行引用abal,但在oracle中,您无法在having子句中引用列别名,因此请使用聚合AVG(currbal)。此外,Oracle不允许group by子句中的子查询,但是,您在第4行中执行的操作的要点是确保AVG(currbal)小于该分支的某些currbal值,可能是{{1} }?

总而言之,这提供了你正在寻找的答案,虽然我不确定你甚至需要有条款,因为它会消除平均余额等于最大余额(MAX(currbal) s与单个记录或branchno的所有记录具有相同的余额):

branchno