在一列上使用 'group by' 但获取多列数据
Use 'group by' on one column but get data of multiple columns
您如何设法在一列上创建 'group by' 并仍然在其他列上获取数据(真实数据,而不是 'sum')?
让我举个例子说明我想做什么:
假设 表 A,索引在“Group”上,一个简单的 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 请求是错误的:无论抛出 having count(*)
上的什么条件,max(rowid)
都将保持不变。
可能有一些 pivot
可以使用,但我真的不知道如何使用它,因为我只有一个 table 并且需要获取所有数据。
为了更精确,我不需要按特定顺序得到结果 table,我可以将自己限制在 4 张专辑,因为我知道每个 'Group' 不会有更多...但我会喜欢一些通用的东西。
编辑:好吧,似乎我忘记澄清我在 Oracle 10g 上(该死的遗留代码 ^^)所以像 PIVOT
这样的新功能将不起作用。
另外,我不是在寻找像 LISTAGG
这样的字符串聚合,而是在寻找单独的列。
@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
。
我相信这应该适用于 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 安装,现在,所以我无法测试它。
您如何设法在一列上创建 'group by' 并仍然在其他列上获取数据(真实数据,而不是 'sum')?
让我举个例子说明我想做什么:
假设 表 A,索引在“Group”上,一个简单的 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 请求是错误的:无论抛出 having count(*)
上的什么条件,max(rowid)
都将保持不变。
可能有一些 pivot
可以使用,但我真的不知道如何使用它,因为我只有一个 table 并且需要获取所有数据。
为了更精确,我不需要按特定顺序得到结果 table,我可以将自己限制在 4 张专辑,因为我知道每个 'Group' 不会有更多...但我会喜欢一些通用的东西。
编辑:好吧,似乎我忘记澄清我在 Oracle 10g 上(该死的遗留代码 ^^)所以像 PIVOT
这样的新功能将不起作用。
另外,我不是在寻找像 LISTAGG
这样的字符串聚合,而是在寻找单独的列。
@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
。
我相信这应该适用于 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 安装,现在,所以我无法测试它。