Cla*_*key 4 sql oracle group-by function user-defined-functions
在 Oracle 中,是否可以根据用户定义函数的输出对数据进行分组?当我尝试这样做时,我遇到了错误,下面的示例最好地说明了这一点:
我正在尝试询问类似于下面的表结构的结果:
id   | data
1000 | {abc=123, def=234, ghi=111, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=123, def=234, ghi=222, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=123, def=434, ghi=333, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=123, def=434, ghi=444, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=123, def=634, ghi=555, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=923, def=634, ghi=666, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=923, def=434, ghi=777, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=923, def=434, ghi=888, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=923, def=234, ghi=999, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
1000 | {abc=923, def=234, ghi=000, jkl=456, mno=567, pqr=678, stu=789, vwx=890, yza=901}
还有其他列,只是没有显示。id 列可以有不同的值,但在本例中没有。数据列中,只有abc、def、ghi字段不同,其他都一样。同样,这仅用于说明该数据示例。
我编写了一个函数来提取分配给数据列中字段的值,并在以下查询中使用它:
select id
      ,extract_data(data,abc) as abc
      ,extract_data(data,def) as def
from   table
给出结果:
id   | abc | def
1000 | 123 | 234
1000 | 123 | 234
1000 | 123 | 434
1000 | 123 | 434
1000 | 123 | 634
1000 | 923 | 634
1000 | 923 | 434
1000 | 923 | 434
1000 | 923 | 234
1000 | 923 | 234
出于报告目的,我希望能够显示每种类型记录的数量。上面的例子有 6 种类型,理想情况下输出是:
id   | abc | def | count
1000 | 123 | 234 | 2
1000 | 123 | 434 | 2
1000 | 123 | 634 | 1
1000 | 923 | 634 | 1
1000 | 923 | 434 | 2
1000 | 923 | 234 | 2
我希望通过像这样编写 SQL 来实现这一点(并且我确信我过去已经这样做过):
select id
      ,extract_data(data,abc) as abc
      ,extract_data(data,def) as def
      ,count(1)
from   table
group by id
        ,abc
        ,def
然而,这是行不通的。Oracle 给我一个错误:
ORA-00904: “ABC”: 无效标识符 00904。00000 - “%s: 无效标识符”
从我对“谷歌”的初步研究中,我发现我也许应该对我传递给用户定义函数的列进行分组。这是因为 SQL 要求所有不属于聚合函数的列都需要成为 group by 子句的一部分。
这适用于某些记录,但是在我的数据示例中,数据列中的字段 ghi 对于每个记录都是不同的,从而使数据列唯一,并破坏 group by 子句,因为每个记录的计数为 1 。
我过去使用过 sybase 和 db2,并且(让自己在这里跌倒……)我非常确定我能够对用户定义函数的输出进行分组。
我认为列的命名以及分组依据如何引用它们可能存在问题?按列号引用不起作用。
我已经尝试了我所拥有的各种组合,但无法使其发挥作用,所以我很感激你们能提供的任何见解。
如果您需要更多信息,我将根据需要进行编辑或在评论中进行澄清。
谢谢,GC。
您应该能够按函数本身而不是别名进行分组
select id
      ,extract_data(data,abc) as abc
      ,extract_data(data,def) as def
      ,count(*)
from   table
group by id
        ,extract_data(data,abc)
        ,extract_data(data,def) 
请注意,这通常不涉及多次执行该函数。您可以看到自己使用了一个简单的函数,每次调用它时都会增加包中的计数器
SQL> ed
Wrote file afiedt.buf
  1  create or replace package pkg_counter
  2  as
  3    g_cnt integer := 0;
  4* end;
SQL> /
Package created.
SQL> create or replace function f1( p_arg in number )
  2    return number
  3  is
  4  begin
  5    pkg_counter.g_cnt := pkg_counter.g_cnt + 1;
  6    return mod( p_arg, 2 );
  7  end;
  8  /
Function created.
EMP表中有16行
SQL> select count(*) from emp;
  COUNT(*)
----------
        16
因此,当我们执行涉及按函数调用进行分组的查询时,我们希望看到该函数仅执行 16 次。事实上,这就是我们所看到的。
SQL> select deptno,
  2         f1( empno ),
  3         count(*)
  4    from emp
  5   group by deptno,
  6            f1( empno );
    DEPTNO  F1(EMPNO)   COUNT(*)
---------- ---------- ----------
                    1          1
        30          0          4
        20          1          1
        10          0          2
        30          1          2
        20          0          4
        10          1          1
                    0          1
8 rows selected.
SQL> begin
  2    dbms_output.put_line( pkg_counter.g_cnt );
  3  end;
  4  /
16
PL/SQL procedure successfully completed.