SQL Group By 根据用户定义函数的输出

发布于 2024-11-29 03:40:02 字数 2494 浏览 2 评论 0原文

在 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:无效标识符”

从我对“google”的初步研究中,我发现我也许应该对传递给用户定义函数的列进行分组。这是因为 SQL 要求所有不属于聚合函数的列都需要成为 group by 子句的一部分。

这适用于某些记录,但是在我的数据示例中,数据列中的字段 ghi 对于每个记录都是不同的,从而使数据列唯一,并破坏 group by 子句,因为每个记录的计数为 1 。

我过去使用过 sybase 和 db2,并且(让自己在这里跌倒……)我非常确定我能够对用户定义函数的输出进行分组。

我认为列的命名以及分组依据如何引用它们可能存在问题?按列号引用不起作用。

我已经尝试了我所拥有的各种组合,但无法使其发挥作用,所以我很感激你们能提供的任何见解。

如果您需要更多信息,我将根据需要进行编辑或在评论中进行澄清。

谢谢, GC。

Is it possible, in Oracle, to group data on the output of a user defined function? I get errors when I try to, and it best illustrated by the below example:

I am trying to interrogate results in table structure similar to below:

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}

There are other columns, just not shown. The id column can have different values, but in this example, does not. In the data column, only the fields abc, def, and ghi differ, all the others are the same. Again this is only illustrative for this data example.

I have written a function to extract the value assigned to fields in the data column, and it is used in the following query:

select id
      ,extract_data(data,abc) as abc
      ,extract_data(data,def) as def
from   table

giving results:

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

For reporting purposes, I would like to be able to display the amount of each type of record. There are 6 types in the above example, and ideally the output would be:

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

I expected to achieve this by writing SQL like so (and I'm convinced I have done so in the past):

select id
      ,extract_data(data,abc) as abc
      ,extract_data(data,def) as def
      ,count(1)
from   table
group by id
        ,abc
        ,def

This however, will not work. Oracle is giving me an error of:

ORA-00904: "ABC": invalid identifier
00904. 00000 - "%s: invalid identifier"

From my initial research on "the google", I have seen that I should perhaps be grouping on the column I am passing into my user defined function. This would be due to SQL requiring all columns not part of an aggregate function needing to be part of the group by clause.

This will work for some records, however in my data example, the field ghi in the data column is different for every record , thus making the data column unique, and ruining the group by clause, as a count of 1 is given for each record.

I've used sybase and db2 in the past, and (setting myself up for a fall here...) I'm pretty sure in both that I was able to group by on the output of a user defined function.

I thought that there might be an issue with the naming of the columns and how they can be referenced by the group by? Referencing by column number hasn't worked.

I've tried various combinations of what I have, and can't get it to work, so I'd appreciate any insight you guys out there could give.

If you need any more information I'll edit as required or clarify in the comments.

Thanks,
GC.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

流年里的时光 2024-12-06 03:40:02

您应该能够按函数本身进行分组,而不是按别名进行分组。

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.

You should be able to group by the functions themselves, not by the aliases

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) 

Note that this does not generally involve executing the function multiple times. You can see that yourself with a simple function that increments a counter in a package every time it is called

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.

There are 16 rows in the EMP table

SQL> select count(*) from emp;

  COUNT(*)
----------
        16

so when we execute a query that involves grouping by the function call, we hope to see the function executed only 16 times. And that is, in fact, what we see.

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.
风吹过旳痕迹 2024-12-06 03:40:02

试试这个:

select id, abc, def, count(1)
from
(
    select 
      id,
      extract_data(data,abc) as abc,
      extract_data(data,def) as def
    from   table 
)
group by id, abc, def 

Try this:

select id, abc, def, count(1)
from
(
    select 
      id,
      extract_data(data,abc) as abc,
      extract_data(data,def) as def
    from   table 
)
group by id, abc, def 
一直在等你来 2024-12-06 03:40:02

你有没有尝试过:

SELECT
    id,
    extract_data(data, abc) as abc,
    extract_data(data, def) as def,
    COUNT(1)
FROM
    table
GROUP BY
    id,
    extract_data(data, abc)
    extract_data(data, def)

Have you tried:

SELECT
    id,
    extract_data(data, abc) as abc,
    extract_data(data, def) as def,
    COUNT(1)
FROM
    table
GROUP BY
    id,
    extract_data(data, abc)
    extract_data(data, def)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文