如何将列的子集转置为行并按其余行进行分组?优秀? SQL?

问题描述 投票:0回答:1

我们正处于将一些数据从遗留系统迁移到似乎有一些怪癖的新系统的早期阶段。

目前我们有一些数据如下

Name      Date      Award
Roger  2024-06-01     A1
Roger  2024-06-01     A2
Roger  2024-07-01     A3
Alice  2024-06-01     A4
Alice  2024-07-01     A5
Aidan  2024-01-01     A6

我试图将数据转换为以下格式

Name   2024-06-01  2024-06-01  2024-07-01  2024-01-01
Roger       A1         A2          A3          -
Alice       A4          -          A5          -
Aidan       -           -          -           A6

数据的几个问题是行数可以变化。因此,当旋转时,列数也可以是可变的。另一个问题是,如果我试图以“日期”为中心,有时一个人可能会在一天内获得多个奖项,因此“日期”列也可以重复几次。

我尝试进行搜索,发现了一些不同的解决方案,其中一个是通过 SQL(我们的数据来自 Oracle),下一个选项是 Excel Power Query。

当我搜索SQL解决方案时,我发现Oracle有pivot函数,但这需要聚合。然后我发现也许我可以使用 MAX 或 MIN 函数(条件聚合?) - 但不幸的是,这会导致一些数据丢失 -> 例如,2024 年 6 月 1 日的“Roger”只有一个奖项在输出中。

在寻找 Excel 选项时,我找到了一篇建议使用 Excel Power Query 来透视表数据的文章。这似乎工作正常,直到我碰到这一行:

Name      Date      Award
Roger  2024-06-01     A1
Roger  2024-06-01     A2

它引发了一个错误,暗示由于 2024-06-01 有 2 个值,它无法将行聚合到列。同样,如果我使用 MAX/MIN,它会修复错误,但随后我会丢失 A1 或 A2 奖励数据。

我知道 Pivot 从根本上来说是为了聚合/分组值,所以我很难找到如何获得所需的输出。不确定 SQL 或 Excel 是否是解决问题的最佳方式,或者这是否完全是无意义的请求,我将不胜感激任何想法或意见

sql excel oracle pivot powerquery
1个回答
0
投票

您可以在旋转之前操作源,所以(使用 SQL Server)我这样做了

with cteBase as
(
    select 
    t.name,t.date,
    STRING_AGG(t.award,',')  as awards
    from #t as t
    group by t.name,t.date
)
select 
*
from
cteBase as base
pivot
(
    max(awards) for [date] in ([2024-01-01],[2024-06-01],[2024-07-01])
) as pvt
order by name

这给出了

enter image description here

不确定最佳解决方案的想法,但会有办法使其成为可能:)

© www.soinside.com 2019 - 2024. All rights reserved.