sql - 在子查询条件中使用组内行的值

标签 sql oracle group-by subquery

假设 Oracle 数据库中有以下表:

  • TBL_A 包含列 IDC_1C_2C_3、 ..., C_20(主键:ID)
  • TBL_B 包含列 IDA_IDC_1C_2C_3、...、C_20(外键 A_ID 引用 TBL_A.ID)
  • TBL_CTBL_D 等,与 TBL_B 具有相同的通用布局

现在,我正在尝试基于对 TBL_A 中的行进行分组来构建报告,同时例如从附加表(TBL_BTBL_C 等)聚合不同数据(总和、计数、最小/最大/平均值等),其中一些附加条件已满足。

如果主查询基于 TBL_A 中的选择,我的问题可能归结为如何(如果可能的话)在子查询中连接来自 TBL_x 的数据> 使用 GROUP BY 子句,例如像这样:

select a.c_1,
count(a.id) as cnt, -- number of matches in TBL_A for this group
(select count(*) from tbl_b b where b.a_id = a.id and b.c_1 = 2) as b_cnt,
(select sum(c_5) from tbl_c c where c.a_id = a.id and c.c_3 = 3) as c_sum
from tbl_a a
where ...
group by a.c_1;

即使Oracle不会执行这段代码(ORA-00979,a.id不是GROUP BY表达式),我希望查询的目的应该是显而易见的。在本例中,我需要一个四列结果集:

  1. TBL_A.C_1 的所有不同值。
  2. 该组中 TBL_A 的行数。
  3. TBL_B 中的行数,其中 C_1 = 2A_IDTBL_A 中的任意行> 包含在该组中。
  4. TBL_B 中各行的 C_5 总和,其中 C_3 = 3A_ID 指的是以下任意一个该组中包含的 TBL_A 中的行。

我知道我可以重写子查询,以便 group-by 列在 where 子句中重复,例如仅对其中一列进行这样的操作:

select a.c_1,
(select count(*) from tbl_b b, tbl_a a2 
    where a2.c_1 = a.c_1 and b.a_id = a2.id and b.c_1 = 2) as b_cnt_2
from tbl_a a
where ...
group by a.c_1;

但在这种情况下,我必须在所有子查询中重复所有 group by 列和外部 where 子句,因为实际上 where 子句相当长,而且我在 group by 子句中有相当多的列,以及许多子查询引用与 TBL_A 具有不同关系的不同表,SQL 语句最终可能会变得一团糟。

在 Oracle 中是否真的不可能像我在第一个示例中尝试的那样在子查询中使用组内各个行的值(b.a_id = a.id 以及 a.id 中的 b.a_id 失败)?我也考虑过用listagg做一些技巧,但是Oracle似乎不接受子查询子句中的任何聚合函数(这里不允许ORA-00934组函数)。我会理解外部 where 子句的限制,但不明白为什么在子查询 where 子句中不允许这样做。

我尝试通过使用外连接连接附加表(TBL_BTBL_C 等)而不是编写子查询来实现查询,但这会扩展结果(创建所有涉及表的多种组合)在分组之前,以便聚合函数多次考虑同一行。例如。如果 TBL_B 中的两行引用 TBL_A 中的一行,count(a.id) 会计算 TBL_A< 中的同一行 两次。

有人知道如何继续吗?

最佳答案

可能最简单的方法是使用子查询或 CTE:

with a as (
      select a.c_1, a.id,
             count(a.id) as cnt, -- number of matches in TBL_A for this group
             (select count(*) from tbl_b b where b.a_id = a.id and b.c_1 = 2) as b_cnt,
             (select sum(c_5) from tbl_c c where c.a_id = a.id and c.c_3 = 3) as c_sum
      from tbl_a a
      where ...
      group by a.id
     )
select a.c_1,
       sum(cnt) as cnt,
       sum(b_cnt) as b_cnt,
       sum(c_sum) as c_sum
from a
group by a.c_1;

这对于大多数聚合函数来说都可以正常工作。如果您有 avg(),则分别进行求和和计数,然后将总计除以平均值。如果您有一个 count(distinct) 那么这将不起作用。你的问题没有这些。

关于sql - 在子查询条件中使用组内行的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26002995/

相关文章:

mysql - 使用两个查询制作水平 View

oracle - 数据库对象代码生成的资源

mysql - 如何对 sql select 语句进行排序,以便正确显示排行榜?

asp.net - Oracle/ASP.NET 环境的最佳源代码控制解决方案?

mysql right join with group by 问题

mysql - 如何在 MySQL 中按年和月分组

sql - 我将如何为附加报告编写 SQL?

mysql - INSERT INTO 且 SELECT COUNT 子查询返回 null

PHP 和 Javascript

c# - 如何将表值参数从 C# 传递到 Oracle 存储过程