假设 Oracle 数据库中有以下表:
TBL_A
包含列ID
、C_1
、C_2
、C_3
、 ...,C_20
(主键:ID
)TBL_B
包含列ID
、A_ID
、C_1
、C_2
、C_3
、...、C_20
(外键A_ID
引用TBL_A.ID
)TBL_C
、TBL_D
等,与TBL_B
具有相同的通用布局
现在,我正在尝试基于对 TBL_A
中的行进行分组来构建报告,同时例如从附加表(TBL_B
、TBL_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表达式),我希望查询的目的应该是显而易见的。在本例中,我需要一个四列结果集:
TBL_A.C_1
的所有不同值。- 该组中
TBL_A
的行数。 TBL_B
中的行数,其中C_1 = 2
和A_ID
指TBL_A
中的任意行> 包含在该组中。TBL_B
中各行的C_5
总和,其中C_3 = 3
和A_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_B
、TBL_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/