我再次与GROUP BY
斗争。我可以处理的基础知识,但它是:如何在不破坏我的分组的情况下访问group by
中命名的不同列?请注意,group by
只是我自己的想法,可能有其他更好的方法。但它必须在Oracle中运行。
以下是我的例子:
create table xxgroups (
groupid int not null primary key,
groupname varchar2(10)
);
insert into xxgroups values(100, 'Group 100');
insert into xxgroups values(200, 'Group 200');
drop table xxdata;
create table xxdata (
num1 int,
num2 int,
state_a int,
state_b int,
groupid int,
foreign key (groupid) references xxgroups(groupid)
);
-- "ranks" are 90, 40, null, 70:
insert into xxdata values(10, 10, 1, 4, 100);
insert into xxdata values(10, 10, 0, 4, 200);
insert into xxdata values(11, 11, 0, 3, 100);
insert into xxdata values(20, 22, 5, 7, 200);
任务是为每个distinct (num1, num2)
创建一个结果行,并打印groupname
来自state_a
和state_b
的最高计算“排名”。
请注意,前两行具有相同的
num
s,因此只应选择较高的排名 -groupname
为“Group 200”。
我认为基本的group by
已经相当远了。
SELECT xd.num1||xd.num2 nummer, max(ranking.goodness)
FROM xxdata xd
, xxgroups xg
,( select state_a, state_b, r as goodness
from dual
model return updated rows
dimension by (0 state_a, 0 state_b) measures (0 r)
rules (r[1,4]=90, r[3,7]=80,r[5,7]=70, r[4,7]=60, r[0,7]=50, r[0,4]=40)
order by goodness desc
) ranking
WHERE xd.groupid=xg.groupid
and ranking.state_a (+) = xd.state_a
and ranking.state_b (+) = xd.state_b
GROUP BY xd.num1||xd.num2
ORDER BY nummer
;
结果是我需要的90%:
nummer ranking
----------------
1010 90
1111
2022 70
100%完美将是
nummer groupname
-------------------
1010 Group 100
1111 Group 100
2022 Group 200
groupname
。而且我不能将其包含在select
中,因为我会将放入group by
中 - 我做而不是希望(然后我不会从所有组中选择最佳排名条目)model
表来计算“排名”。我确信还有其他解决方案。关键是,这是一个非常重要的计算,我不想做两次。groupname
,但我无法在此处看到这样做,
没有重复我的排名计算。group by
替换为LIMIT 1
/ ORDER BY goodness
,并使用此计算选择作为过滤子选择。但是a)Oracle中没有LIMIT
,我怀疑rownum<=1
会在子选择中做什么,而b)无论如何我无法绕过它。也许有办法?答案 0 :(得分:4)
您可以使用FIRST
聚合修饰符有选择地将您的函数应用于组的一部分行 - 这里是一行(SQLFiddle demo):
SELECT xd.num1||xd.num2 nummer,
MAX(xg.groupname) KEEP (DENSE_RANK FIRST
ORDER BY ranking.goodness DESC) grp,
max(ranking.goodness)
FROM xxdata xd
, xxgroups xg
,( select state_a, state_b, r as goodness
from dual
model return updated rows
dimension by (0 state_a, 0 state_b) measures (0 r)
rules (r[1,4]=90, r[3,7]=80,r[5,7]=70, r[4,7]=60, r[0,7]=50, r[0,4]=40)
order by goodness desc
) ranking
WHERE xd.groupid=xg.groupid
and ranking.state_a (+) = xd.state_a
and ranking.state_b (+) = xd.state_b
GROUP BY xd.num1||xd.num2
ORDER BY nummer;
您使用分析的方法也可以,但由于我们已在此处使用聚合,因此我们也可以使用FIRST
修饰符一次性获取所有列。
答案 1 :(得分:2)
我以前做过搜索,但现在我找到了this answer,我可以对我提出这个问题。这里的Oracle解决方案是over
,partition by
order by
和row_number()
:
select *
from ( select data.*, row_number()
over (partition by nummer order by goodness desc) as seqnum
from (
SELECT xd.num1, xd.num2 nummer, xg.groupname, ranking.goodness
FROM xxdata xd
, xxgroups xg
,( select state_a, state_b, r as goodness
from dual
model return updated rows
dimension by (0 state_a, 0 state_b) measures (0 r)
rules (r[1,4]=90, r[3,7]=80,r[5,7]=70, r[4,7]=60, r[0,7]=50, r[0,4]=40)
) ranking
WHERE xd.groupid=xg.groupid
and ranking.state_a (+) = xd.state_a
and ranking.state_b (+) = xd.state_b
ORDER BY nummer
) data )
where seqnum = 1
;
结果是
10 10 Group 100 90 1
11 11 Group 100 1
20 22 Group 200 70 1
很漂亮。
现在我必须尝试了解over
中select
的确切含义....