SQL 服务器 - 有条件地转置数据

SQL Server - transpose data conditionally

我有如下图所示的数据集: Original dataset

我需要构建如下报告: Report needed

基本上每个人在 PersonLang 中都有一些条目 table。这些条目代表每个语言技能组合加上级别的一行。

该报告应包含一个人知道的所有语言,按分数(级别)的降序排列。先高级后中等

到目前为止我已经尝试了一些事情:

  1. 我尝试使用 PIVOT,但我事先不知道一个人的所有语言,而且如果一个人只知道一种语言,它应该出现在第一列中
  2. 我尝试使用按 personid 分区并按语言级别排序的 window 函数 (Lead)。在这里我遇到了问题,因为我需要每种语言的所有技能一行
  3. 我正在考虑编写一个 table 值函数,它将原始数据集作为游标,然后将其转换为所需的 table。在这里,我在同一行中插入所有值时遇到问题,如果语言在同一级别出现两次,我应该只更新级别。

我想我想多了,也许头脑更清醒的人可以指出正确的解决方案。应该对原始数据集应用什么才能获得所需的结果?

SQL 语句复制数据:

create table personlang(
  personid number,
  lang varchar2(20),
  langskill varchar2(20),
  lvl varchar2(20),
  score number)


 insert into personlang values (101, 'Dutch', 'Spoken', 'Advanced', 3);
 insert into personlang values (101, 'Dutch', 'Written', 'Medium', 2);
 insert into personlang values (101, 'French', 'Spoken', 'Medium', 2);
 insert into personlang values (101, 'Arabic', 'Written','Begineer',1);
 insert into personlang values (102, 'English', 'Spoken','Advanced',3);

提前致谢

     DECLARE @sql NVARCHAR(max),@col NVARCHAR(max)

     SELECT @col=ISNULL(@col+',','')+'[ForeignLand'+n.LangID+'],[ForeignLand'+n.LangID+'Spoken],['+'ForeignLand'+n.LangID+'Written]'
     FROM (
       SELECT DISTINCT CONVERT(VARCHAR,DENSE_RANK()OVER(PARTITION BY personid ORDER BY lang)) AS LangID
       FROM personlang 
     ) n
     PRINT @col
     SELECT @sql='
     SELECT * FROM (
         SELECT l.personid,c.* FROM (
           SELECT *, DENSE_RANK()OVER(PARTITION BY pl.personid ORDER BY lang) AS LangID FROM personlang AS pl
         ) l
         CROSS APPLY (VALUES(''ForeignLand''+CONVERT(VARCHAR,LangID),lang)
                           ,(''ForeignLand''+CONVERT(VARCHAR,LangID)+''Spoken'',CASE WHEN langskill=''Spoken'' THEN lvl ELSE NULL END )
                           ,(''ForeignLand''+CONVERT(VARCHAR,LangID)+''Written'',CASE WHEN langskill=''Written'' THEN lvl ELSE NULL END )
         ) c(col_title,col_value)
     )m
     PIVOT(MAX(m.col_value) FOR m.col_title IN('+@col+')) p'

     exec(@sql)

personid    ForeignLand1         ForeignLand1Spoken   ForeignLand1Written  ForeignLand2         ForeignLand2Spoken   ForeignLand2Written  ForeignLand3         ForeignLand3Spoken   ForeignLand3Written
----------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
101         Arabic               NULL                 Begineer             Dutch                Advanced             Medium               French               Medium               NULL
102         English              Advanced             NULL                 NULL                 NULL                 NULL                 NULL                 NULL                 NULL