SQL 中的聚合总和(连接)
Aggregation Sum in SQL (Joins)
我在使用聚合对查询中的某些列求和时遇到了一些问题。
描述正在发生的事情有点困难,但我会尽力而为:
我有 3 tables - 详细信息、额外的详细信息和位置。
Places 是一个包含世界各地的 table。详细信息包含有关已发生事件的详细信息,额外详细信息提供有关事件的更多数据。
每个地方都有一个 ID
和一个 ParentID
(就像纽约有一个 ID
而它的父 ID
是 US
。类似那)。事件(详细信息)的 ID
作为额外详细信息 table 中的一列出现了多次。额外的详细信息 table 还包含事件发生地点的 ID
。
好的,毕竟,我想要实现的是,对于每个地方,那里发生的事件的总和。我知道这听起来很具体,但这是客户要求的。
无论如何,我想要达到的目标示例:
纽约60个,芝加哥20个,休斯敦10个,然后美国就有90个了,而且有好几个级别。
所以这就是我想要做的:
With C(ID, NAME, COUNTT, ROOT_ID) as
(
SELECT d.ID, d.NAME,
(SELECT COUNT(LX.ID) as COUNTT
FROM EXTRA LX
RIGHT JOIN d ON LX.PLACE_ID = d.ID -- ****
GROUP BY d.ID, d.NAME),
d.ID as ROOT_ID
FROM PLACES d
UNION ALL
SELECT d.ID, d.NAME,
(SELECT COUNT(LX.ID) as COUNTT
FROM EXTRA LX
RIGHT JOIN d ON LX.PLACE_ID = d.ID
GROUP BY d.ID, d.NAME),
C.ROOT_ID
FROM PLACES dx
INNER JOIN C ON dx.PARENT_ID = C.ID
)
SELECT p.ID, p.NAME, S.SumIncludingChildren
FROM places p
INNER JOIN (
SELECT ROOT_ID, SUM(COUNTT) as SumIncludingChildren
FROM C
GROUP BY ROOT_ID
) S
ON p.ID = S.ROOT_ID
ORDER BY p.ID;
详情table只是为了展示他们的数据。我稍后再补充。它只是比较各自的列。为了让它工作,我不需要那个。仅适用于站点数据。
它不起作用,因为它无法识别“****”所在的 'd'。如果我将那个 table 的 'new instance' 放上去,它也不会起作用。因此,我尝试通过对获取所有位置的查询执行 'NOT EXISTS IN'
来复制正确的连接,而不是正确的连接...。同样的问题。
也许我没有得到什么。但我真的在寻求解决方案和一些解释。我知道我的代码并不完美。
提前致谢。
编辑:我在 Toad 10.6 上使用 OracleSQL
create table p(id number, up number, name varchar2(100));
create table e(id number, pid number, dsc varchar2(100));
insert into p values (1, null, 'country');
insert into p values (2, 1, 'center');
insert into p values (3, 1, 'province');
insert into p values (4, 2, 'capital');
insert into p values (5, 2, 'suburb');
insert into p values (6, 3, 'forest');
insert into p values (7, 3, 'village');
insert into p values (8, 7, 'shed');
insert into p values (9, 2, 'gov');
insert into e values (1, 8, 'moo');
insert into e values (2, 8, 'clank');
insert into e values (3, 7, 'sowing');
insert into e values (4, 6, 'shot');
insert into e values (5, 6, 'felling');
insert into e values (6, 5, 'train');
insert into e values (7, 5, 'cottage');
insert into e values (8, 5, 'rest');
insert into e values (9, 4, 'president');
insert into e values (10,1, 'GNP');
commit;
with
places as
(select id,
up,
connect_by_root id as root,
level lvl
from p
connect by prior id = up),
ev_stats as
(select root as place, max(lvl) as max_lvl, count(e.id) as ev_count
from places left outer join e
on places.id = e.pid
group by root)
select max_lvl, p.name, ev_count
from ev_stats inner join p on p.id = ev_stats.place
order by max_lvl desc;
我在使用聚合对查询中的某些列求和时遇到了一些问题。
描述正在发生的事情有点困难,但我会尽力而为:
我有 3 tables - 详细信息、额外的详细信息和位置。
Places 是一个包含世界各地的 table。详细信息包含有关已发生事件的详细信息,额外详细信息提供有关事件的更多数据。
每个地方都有一个 ID
和一个 ParentID
(就像纽约有一个 ID
而它的父 ID
是 US
。类似那)。事件(详细信息)的 ID
作为额外详细信息 table 中的一列出现了多次。额外的详细信息 table 还包含事件发生地点的 ID
。
好的,毕竟,我想要实现的是,对于每个地方,那里发生的事件的总和。我知道这听起来很具体,但这是客户要求的。
无论如何,我想要达到的目标示例:
纽约60个,芝加哥20个,休斯敦10个,然后美国就有90个了,而且有好几个级别。
所以这就是我想要做的:
With C(ID, NAME, COUNTT, ROOT_ID) as
(
SELECT d.ID, d.NAME,
(SELECT COUNT(LX.ID) as COUNTT
FROM EXTRA LX
RIGHT JOIN d ON LX.PLACE_ID = d.ID -- ****
GROUP BY d.ID, d.NAME),
d.ID as ROOT_ID
FROM PLACES d
UNION ALL
SELECT d.ID, d.NAME,
(SELECT COUNT(LX.ID) as COUNTT
FROM EXTRA LX
RIGHT JOIN d ON LX.PLACE_ID = d.ID
GROUP BY d.ID, d.NAME),
C.ROOT_ID
FROM PLACES dx
INNER JOIN C ON dx.PARENT_ID = C.ID
)
SELECT p.ID, p.NAME, S.SumIncludingChildren
FROM places p
INNER JOIN (
SELECT ROOT_ID, SUM(COUNTT) as SumIncludingChildren
FROM C
GROUP BY ROOT_ID
) S
ON p.ID = S.ROOT_ID
ORDER BY p.ID;
详情table只是为了展示他们的数据。我稍后再补充。它只是比较各自的列。为了让它工作,我不需要那个。仅适用于站点数据。
它不起作用,因为它无法识别“****”所在的 'd'。如果我将那个 table 的 'new instance' 放上去,它也不会起作用。因此,我尝试通过对获取所有位置的查询执行 'NOT EXISTS IN'
来复制正确的连接,而不是正确的连接...。同样的问题。
也许我没有得到什么。但我真的在寻求解决方案和一些解释。我知道我的代码并不完美。
提前致谢。
编辑:我在 Toad 10.6 上使用 OracleSQL
create table p(id number, up number, name varchar2(100));
create table e(id number, pid number, dsc varchar2(100));
insert into p values (1, null, 'country');
insert into p values (2, 1, 'center');
insert into p values (3, 1, 'province');
insert into p values (4, 2, 'capital');
insert into p values (5, 2, 'suburb');
insert into p values (6, 3, 'forest');
insert into p values (7, 3, 'village');
insert into p values (8, 7, 'shed');
insert into p values (9, 2, 'gov');
insert into e values (1, 8, 'moo');
insert into e values (2, 8, 'clank');
insert into e values (3, 7, 'sowing');
insert into e values (4, 6, 'shot');
insert into e values (5, 6, 'felling');
insert into e values (6, 5, 'train');
insert into e values (7, 5, 'cottage');
insert into e values (8, 5, 'rest');
insert into e values (9, 4, 'president');
insert into e values (10,1, 'GNP');
commit;
with
places as
(select id,
up,
connect_by_root id as root,
level lvl
from p
connect by prior id = up),
ev_stats as
(select root as place, max(lvl) as max_lvl, count(e.id) as ev_count
from places left outer join e
on places.id = e.pid
group by root)
select max_lvl, p.name, ev_count
from ev_stats inner join p on p.id = ev_stats.place
order by max_lvl desc;