4

我确实与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_astate_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 byLIMIT 1/替换ORDER BY goodness并将此计算选择用作过滤子选择。但是a)在Oracle中没有LIMIT,我怀疑arownum<=1会在子选择中做,b)无论如何我都无法绕开它。也许有办法?
4

2 回答 2

4

您可以使用FIRST聚合修饰符有选择地将您的函数应用于组的一部分行 - 这里是单行(SQLFiddle 演示):

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修饰符一次性获取所有列。

于 2012-11-14T12:05:45.893 回答
2

哇,我以前搜索过,但现在我找到了这个答案,我可以采用它来回答我的问题。这里的Oracle 解决方案是over,partition by和:order byrow_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......

于 2012-11-14T11:39:10.983 回答