SQL Server 将行透视为列,并为一个用户保留一行

cs7cruho  于 2022-12-26  发布在  其他
关注(0)|答案(2)|浏览(102)

| 身份证|用户|经理标识|经理姓名|阶层|级别_1|级别_2|级别_3|级别_4|
| - ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|
| 一百|A类|三十|彼得|1个|布赖恩|零|零|零|
| 一百|A类|零|零|第二章|零|科比|零|零|
| 一百|A类|零|零|三个|零|零|彼得|零|
| 二百|B|二十个|科比|1个|零|布赖恩|零|零|
| 二百|B|零|零|第二章|彼得|零|零|零|
| 二百|B|零|零|三个|零|零|科比|零|
| 三百|C级|十个|布赖恩|1个|彼得|零|零|零|
| 三百|C级|零|零|第二章|零|科比|零|零|
| 三百|C级|零|零|三个|零|零|布赖恩|零|
如何将行值透视到现有列,以便为一个用户保留一行?
| 身份证|用户|经理标识|经理姓名|阶层|级别_1|级别_2|级别_3|级别_4|
| - ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|
| 一百|A类|三十|彼得|四个|布赖恩|科比|彼得|零|
| 二百|B|二十个|科比|四个|彼得|布赖恩|科比|零|
| 三百|C级|十个|布赖恩|四个|彼得|科比|布赖恩|零|
注意:每个级别对于每个用户只有一个值。

lb3vh1jj

lb3vh1jj1#

假设每个用户的聚合字段上只有一个值,那么可以对每个非聚合字段使用带有MAX函数的聚合:

SELECT id, [user], 
       MAX(manager_id)   AS manager_id, 
       MAX(manager_name) AS manager_name, 
       MAX(hierarchy) +1 AS hierarchy,
       MAX(level_1)      AS level_1, 
       MAX(level_2)      AS level_2, 
       MAX(level_3)      AS level_3, 
       MAX(level_4)      AS level_4 
FROM tab
GROUP BY id, [user]

检查here演示。

5us2dqdw

5us2dqdw2#

我在这里使用STRING_AGG,因为我不喜欢在每行多个级别为NOT NULL或者用户在不同行中每个级别有多个名称时丢失数据的风险。
如果未发生这种情况,则结果与使用MAXMIN时相同。
如果发生这种情况,我们将得到每个级别的每个名称,而不是只有一个。

SELECT id, 
MAX(user_id) AS user_id, 
MAX(manager_id) AS manager_id, 
MAX(manager_name) AS manager_name, 
MAX(hierarchy) +1 AS hierarchy, 
STRING_AGG(level_1,',') AS level_1,
STRING_AGG(level_2,',') AS level_2,
STRING_AGG(level_3,',') AS level_3,
STRING_AGG(level_4,',') AS level_4  
FROM yourtable
GROUP BY id;

在此重复差异:db<>fiddle
即使考虑到你的说法,每个级别总是只有一个名字,我也不会冒这个险。一周或一个月后,情况可能会有所不同。
旁注:在我的示例中,我将“user”重命名为“user_id”,因为我拒绝使用SQL关键字作为列名或表名。如果不是迫切需要,我建议避免这样做。

相关问题