2016-09-25 188 views
0

我有以下数据,我想透视并根据透视结果得到数字。T-SQL数据透视表数据透视结果

DECLARE @tempMusicSchoolStudent TABLE 
(school VARCHAR(50), 
studentname VARCHAR(50), 
instrumentname VARCHAR(255), 
expertise INT) 

INSERT INTO @tempMusicSchoolStudent(school, studentname, instrumentname, expertise) 
SELECT 'Foster','Matt','Guitar','10' 
UNION 
SELECT 'Foster','Jimmy','Guitar','5' 
UNION 
SELECT 'Foster','Jimmy','Keyboard','8' 
UNION 
SELECT 'Foster','Ryan','Keyboard','9' 
UNION 
SELECT 'Midlothean','Kyle','Keyboard','10' 
UNION 
SELECT 'Midlothean','Mary','Guitar','4' 
UNION 
SELECT 'Midlothean','Mary','Keyboard','7' 

原始数据:

enter image description here

我想结果看起来像下面的数据....

enter image description here

我用得到这个数据下面的sql查询。这个查询的问题是我有一个动态数量的工具(为了简单起见,我在这个例子中只显示了2个)。我想使用数据透视表,因为它会更干净的动态SQL。否则,我必须动态地将每个乐器的表格自动加入到自己的表格中。

SELECT 
    t.school, t.instrumentname, t.expertise, 
    t1.instrumentname, t1.expertise, 
    COUNT(DISTINCT t.studentname) [DistinctStudentCount] 
FROM 
    @tempMusicSchoolStudent t 
LEFT JOIN 
    @tempMusicSchoolStudent t1 ON t1.school = t.school 
           AND t1.studentname = t.studentname 
           AND t.instrumentname <> t1.instrumentname 
GROUP BY 
    t.school, t.instrumentname, t.expertise, t1.instrumentname, t1.expertise 
ORDER BY 
    t.school, t.instrumentname, t.expertise, t1.instrumentname, t1.expertise 

如果有人不是动态左侧的接合部表到它本身将不胜感激我如何能在一个更清洁的方式做到这一点的任何想法。谢谢。

+0

你的输出中row1和row3有什么不同? – p2k

+1

这里没有区别,但它是数据的预期模式。如果我可以删除那些很棒的重复,但现在用户可以很好地完成这些工作,因为他们希望完全连接数据。 – mgmedick

回答

0

这是我一直在寻找,解决我不得不使用逆转置+支点。

我一直在努力的事情是为正在旋转的列选择多个值,而不是最大值。

因此,在这种情况下,我想在给定的“仪器专业知识”栏下找到多个“专家”号码。不仅仅是该仪器的最大专业知识。

理解解决方案的第一个关键是,pivot语句在被选中的列上进行隐式分组。因此,为了在您的透视列下实现多个值,您必须通过包含某种类型的dense_rank/rank/row_number来保持您正在分组的列的完整性。这基本上代表了您正在旋转的列的值的变化,然后通过数据透视表包含在隐式组中,这会导致在透视列中获取多个值,而不仅仅是最大值。

所以在下面的代码中,“expertisenum”列保留了专业知识数据的完整性。

DECLARE @tempMusicSchoolStudent TABLE 
(school VARCHAR(50), 
studentname VARCHAR(50), 
instrumentname VARCHAR(255), 
expertise INT) 

INSERT INTO @tempMusicSchoolStudent(school, studentname, instrumentname, expertise) 
SELECT 'Foster','Matt','Guitar','10' 
UNION 
SELECT 'Foster','Jimmy','Guitar','5' 
UNION 
SELECT 'Foster','Jimmy','Keyboard','8' 
UNION 
SELECT 'Foster','Ryan','Keyboard','9' 
UNION 
SELECT 'Midlothean','Kyle','Keyboard','10' 
UNION 
SELECT 'Midlothean','Mary','Guitar','4' 
UNION 
SELECT 'Midlothean','Mary','Keyboard','7' 



SELECT school, [Guitar expertise], [Keyboard expertise], COUNT(*) [Count] 
FROM 
(
    SELECT school,[expertiseNum], 
    CASE WHEN [Columns]='expertise' THEN instrumentname + ' expertise' 
     END [Columns1], [Values] AS [Values1] 
    FROM 
    (
     SELECT school, studentname, instrumentname, DENSE_RANK() OVER(PARTITION BY school,instrumentname ORDER BY expertise) AS [expertiseNum], 
     CONVERT(VARCHAR(255),expertise) AS [expertise] 
     FROM @tempMusicSchoolStudent 
    ) x 
    UNPIVOT (
     [Values] FOR [Columns] IN ([expertise]) 
    ) unpvt 
) p 
PIVOT (
    MAX([Values1]) FOR [Columns1] IN ([Guitar expertise], [Keyboard expertise]) 
) pvt 
GROUP BY school,[Guitar expertise], [Keyboard expertise] 
1

你只需要有条件聚集:

SELECT t.school, t.instrumentname, t.expertise, t.instrumentname, 
     COUNT(DISTINCT t.studentname) as DistinctStudentCount 
FROM @tempMusicSchoolStudent t 
GROUP BY t.school, t.instrumentname, t.expertise, t.instrumentname; 

您有NULL值的行。这些来自哪里完全不清楚。你的问题集中在一些“旋转”的概念上,看起来你只需要聚合。但它并不能解释NULL行的来源。

+0

它是我需要的一种笛卡尔结果。 因此,例如,我得到的结果的第一行是给我每个不同的学生在寄养,同时弹奏吉他和键盘与5吉他的专业知识和8键盘的专业知识的计数。 然后结果将落在吉他的所有专业知识的培养和交叉加入,这将在寄养的所有键盘专业知识,并获得这些仪器的专业知识发生的不同学生的数量。 – mgmedick

+0

所以第二排的结果是空的是因为有一个孩子在寄养谁只弹吉他,而不是键盘,与10的专业知识。 – mgmedick

1

您可以尝试使其适用于多功能乐器。 Refer

;with cte 
as 
(
SELECT * from 
(SELECT * FROM @tempMusicSchoolStudent t) x 
PIVOT 
(MAX(expertise) FOR instrumentname in ([Guitar], [Keyboard])) y 
) 

SELECT school, studentname, 
expertise = case when Guitar is not null then 'Guitar' else NULL end, 
Guitar AS instrumentname, 
expertise = case when Keyboard is not null then 'Keyboard' else NULL end, 
Keyboard AS instrumentname, 
count(distinct studentname) AS [DistinctStudentCount] 
from cte 
group by school,studentname, Guitar, Keyboard 

OUTPUT:

Foster   Jimmy Guitar 5  Keyboard 8  1 
Foster   Matt Guitar 10 NULL  NULL 1 
Foster   Ryan NULL NULL Keyboard 9  1 
Midlothean  Kyle NULL NULL Keyboard 10  1 
Midlothean  Mary Guitar 4  Keyboard 7  1