使用' group by'在一列上,但获取多列的数据

时间:2015-01-05 17:15:11

标签: sql oracle oracle10g

如何设法在一列上创建“分组依据”并仍然获取其他数据(真实数据,而不是“总和”)?

让我举例说明我想做的事情:

假设表A ,“群组”上的索引,简单select * from A给出:

Group            Album
---------------- ---------------
ABBA             Waterloo
AC/DC            Back in Black
ABBA             Voulez-vous
ABBA             Super Trooper
Imagine Dragons  Night Visions
AC/DC            Highway to Hell
ABBA             The Visitors



我希望得到最终结果如下(知道我不能为一个小组提供超过4张专辑......现在我猜):

Group            Album1          Album2          Album3          Album4
---------------- --------------- --------------- --------------- ---------------
ABBA             Waterloo        Voulez-vous     Super Trooper   The visitors
AC/DC            Back in Black   Highway to Hell Null            Null
Imagine Dragons  Night Visions   Null            Null            Null



到目前为止,我最接近制作我想要的东西的是以下内容:

select tab4.GROUP,
tab1.ALBUM as PN1,
tab2.ALBUM as PN2,
tab3.ALBUM as PN3,
tab4.ALBUM as PN4
from
(
select A.GROUP, A.ALBUM
from A
where A.ROWID in 
  (select max(ROWID) from A 
  where GROUP in (select GROUP from A A group by A.GROUP having count(*) <= 4)
  group by GROUP
  )
) tab4
left join
(
select A.GROUP, A.ALBUM
from A A
where A.ROWID in 
  (select max(ROWID) from A 
  where GROUP in (select GROUP from A A group by A.GROUP having count(*) <= 3)
  group by GROUP
  )
) tab3 on tab4.GROUP = tab3.GROUP
left join
(
select A.GROUP, A.ALBUM
from A A
where A.ROWID in 
  (select max(ROWID) from A 
  where GROUP in (select GROUP from A A group by A.GROUP having count(*) <= 2)
  group by GROUP
  )
)tab2 on tab4.GROUP = tab2.GROUP
left join
(
select A.GROUP, A.ALBUM
from A A
where A.ROWID in 
  (select max(ROWID) from A 
  where GROUP in (select GROUP from A A group by A.GROUP having count(*) <= 1)
  group by GROUP
  )
) tab1 on tab4.GROUP = tab1.GROUP;


我知道为什么上面的SQL请求是错误的:max(rowid)having count(*)被抛出的任何条件下都将保持不变。 可能会有一些pivot被使用,但我真的不知道如何使用它,因为我只有一个表并且需要获取所有数据。

作为更精确的,我不需要按照特定顺序拥有结果表,我可以将自己限制为4张专辑,因为我知道每个''不会超过......但我很欣赏通用的东西。



编辑:好的,似乎我忘了澄清我在使用Oracle 10g(该死的代码^^),因此像PIVOT这样的新功能将无效。 另外,我不是在寻找像LISTAGG那样的字符串聚合,而是在寻找单独的列。

2 个答案:

答案 0 :(得分:1)

@Alex Poole做对了:我不仅错过了10g中PIVOT代码的等价物,还错过了ROW_NUMBER()

所以问题的答案如下:

select 
  tab1.group_name,
  MAX(CASE WHEN tab1.rank_number = 1 THEN tab1.album_name ELSE NULL END) AS ALBUM_1,
  MAX(CASE WHEN tab1.rank_number = 2 THEN tab1.album_name ELSE NULL END) AS ALBUM_2,
  MAX(CASE WHEN tab1.rank_number = 3 THEN tab1.album_name ELSE NULL END) AS ALBUM_3,
  MAX(CASE WHEN tab1.rank_number = 4 THEN tab1.album_name ELSE NULL END) AS ALBUM_4
from (
  select group_name, album_name,
    row_number() over (partition by group_name order by album_name) as rank_number
  from tablea
) tab1
group by tab1.group_name;

不确定我的标题是否适合我遇到的那种问题,我猜我会保留它,因为它也围绕着group by

答案 1 :(得分:0)

相信这应该适用于10i:

with r as (
  select
    group_,
    album,
    row_number() over (partition by group_ order by album) r
  from
    tq84_table_a
)
select
  r.group_,
  max(case when r.r=1 then r.album end) album1,
  max(case when r.r=2 then r.album end) album2,
  max(case when r.r=3 then r.album end) album3,
  max(case when r.r=4 then r.album end) album4
from
  r
group by
  r.group_;

我现在手头没有安装10i,所以我无法测试它。