我正在使用Azure SQL数据库.我有一个以下 struct 的表格,用来跟踪哪些人在不同的时间在不同的岗位上工作.要提供简化版本,请执行以下操作:

CREATE TABLE PersonWorkload
(
WorkloadID INT PRIMARY KEY IDENTITY,
Post VARCHAR(30),
Period VARCHAR(12),
PersonID INT,
GroupID INT,
Notes VARCHAR(100)
)

这是一个数据样本

INSERT INTO PersonWorkload (Post, Period, PersonID, GroupID, Notes)
    VALUES 
    ('Group Leader', 'Q1', 1, 1, NULL),
    ('Group Leader', 'Q2', 1, 1, NULL),
    ('Group Leader', 'Q3', 1, 2, NULL),
    ('Group Leader', 'Q4', 1, 2, NULL),
    ('Security', 'Q1', 3, 3, NULL),
    ('Security', 'Q2', 3, 3, NULL),
    ('Security', 'Q3', 4, 4, NULL),
    ('Security', 'Q4', 4, 4, NULL),
    ('Team member', 'Q1', 7, 5, NULL),
    ('Team member', 'Q2', 7, 5, 'Leaving programme this qtr'),
    ('Team member', 'Q3', 13, 6, NULL),
    ('Team member', 'Q4', 13, 6, NULL),
    ('Team member', 'Q1', 8, 7, NULL),
    ('Team member', 'Q2', 8, 7, NULL),
    ('Team member', 'Q3', 8, 7, NULL),
    ('Team member', 'Q4', 8, 7, NULL),
    ('Team member','Q1',9,8,'Temp posting'),
    ('Team member', 'Q2', 10, 9, NULL),
    ('Team member', 'Q3', 10, 9, NULL),
    ('Team member', 'Q4', 10, 9, NULL),
    ('Comms','Q2',11,10,NULL),
    ('Comms','Q3',11,10,NULL),
    ('Comms','Q4',11,10,NULL)

使用GroupID列是因为有时我需要将这些帖子放在一起处理.新上岗的人 将总是触发新的groupID,但有时一个人可以在一个职位上呆更长的时间,而那段时间 有时可以包含多个组ID(因此,如果一个人在一个职位上工作了一年,可能是1-6月 有一个GroupID,7月到12月有一个不同的GroupID).

有时一次只有一个人担任一个岗位,有时多个人,有时一个岗位上没有人.

我需要旋转这些信息,以便显示每个时期的列,以及谁在每个帖子中工作. 可能每个帖子都有一行或多行.

为此,我创建了一个SQL Pivot查询,并将结果放入一个临时表中.

下面是临时表的一个示例:

CREATE TABLE SampleData (
    Post VARCHAR(100)
    ,GroupID INT
    ,[Q1] INT
    ,[Q2] INT
    ,[Q3] INT
    ,[Q4] INT
    )

...以及填充它的语句:

INSERT INTO SampleData

SELECT * 
FROM
    (SELECT Post, Period, PersonID, GroupID
    FROM PersonWorkload) t
PIVOT 
    (MAX(t.PersonID)
    FOR t.Period IN ([Q1],[Q2],[Q3],[Q4])
    ) pvt

如果我包含了groupID,我将得到来自透视查询的数据,如下所示:

Post GroupID Q1 Q2 Q3 Q4
Group Leader 1 1 1 NULL NULL
Group Leader 2 NULL NULL 1 1
Security 3 3 3 NULL NULL
Security 4 NULL NULL 4 4
Team member 5 7 7 NULL NULL
Team member 6 NULL NULL 13 13
Team member 7 8 8 8 8
Team member 8 9 NULL NULL NULL
Team member 9 NULL 10 10 10
Comms 10 NULL 11 11 11

这接近于我想要的结果--除了我想要"折叠"这些行,看起来更像这样--这表明有时(顶排)一个人全年都在岗位上,有时这个岗位在头几个时段由某人担任,然后另一个人进来(第二排),有时多个人同时担任一个岗位(团队成员)等等.

Post Q1 Q2 Q3 Q4
Group Leader 1 1 1 1
Security 3 3 4 4
Team member 7 7 13 13
Team member 8 8 8 8
Team member 9 10 10 10
Comms NULL 11 11 11

因此,最明显的做法是删除GroupID,我在本报告中无论如何都不需要它.但是,如果我这样做,数据将"过度折叠"(对不起--不知道如何更好地表达它),并且我们将失go 除最低个人ID之外的所有数据.

Post Q1 Q2 Q3 Q4
Comms NULL 11 11 11
Group Leader 1 1 1 1
Security 3 3 4 4
Team member 9 10 13 13

现在,我已经丢失了,例如,作为团队成员的Person ID 7和8,因为它们不是最大PersonID.

有办法做到这一点吗?我已经做了两天了,但是没能拿到我需要的东西.

这是一个简化的版本--实际上大约有40个职位,报告需要有15个时间段.

感谢您给予的任何帮助.

谢谢

推荐答案

正如@lptr在 comments 中提到的:

您可以向透视表添加行编号列,以确保不合并唯一行.

SELECT * 
FROM (
    SELECT
      Post,
      Period,
      PersonID,
      dense_rank() over (partition by Post, Period order by GroupID, PersonID) as rn
    FROM PersonWorkload
) t
PIVOT 
    (MAX(t.PersonID)
    FOR t.Period IN ([Q1],[Q2],[Q3],[Q4])
    ) pvt;

db<>fiddle

ROW_NUMBER()个人也应该在这里工作

Sql相关问答推荐

SQL从同一表连接列

使用Mac日志(log)时间找出SQL中的好小时和坏小时

为什么两个不同的窗口函数给出不同的排序结果?

如何使用SQL Server中的Nodes()方法执行与OPENXML相同的操作

我需要一个regexp_like来只验证字母D或T、数字和管道

比较SQL中以逗号分隔的字符串

如何在Postgres中为单值输入多行?

更正用于判断错误组合的SQL

将 jsonb 数组中的对象取消嵌套到单独的行中

Spark / Hive:如何获取列中正值的百分比?

如何使用 join 和 where 子句从另一表中仅删除一个表中的值

如何在sparksql查询中使用日期值?

在Snowflake中,如何将以逗号和连字符分隔的多个混合数值拆分成数字列表

Postgres数据库维护:基于GROUP BY删除旧记录

Teradata 多个进程的最大进程结束时间捕获

计算 PostgreSQL 中的平均会话长度

查找具有相同连接列数据的所有记录

在 PostgreSQL 中,如何将数组中的每个元素用作另一个表中的键?

Oracle SQL 查询自行运行,但在包装到select count(*) from ()时失败

聚合 Athena 中的列