T-SQL 枢轴,对枢轴结果进行计数

T-SQL pivot with count on pivoted results

我有以下数据,我想对它们进行透视并根据透视后的结果进行计数。

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'

原始数据:

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

我使用下面的 sql 查询获得了这些数据。这个查询的问题是我有一个动态数量的工具(为了简单起见,我在这个例子中只显示了 2 个)。我想使用 pivot,因为它会更清晰动态 sql。否则,我将不得不为每个乐器动态地将 table 加入自身。

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

如果有人对我如何以一种比动态左连接 table 更简洁的方式做到这一点有任何想法,我们将不胜感激。谢谢。

您只需要条件聚合:

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 个值的行。完全不清楚这些是从哪里来的。您的问题集中在 "pivoting" 的某些概念上,您似乎只需要聚合。但它没有解释 NULL 行的来源。

您可以尝试使其针对多种乐器动态化。

;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

输出:

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

这是我一直在寻找的解决方案,我不得不使用 unpivot + pivot。

真正让我苦恼的是为要旋转的列选择多个值,而不是最大值。

所以在这种情况下,我希望在给定的 "instrument expertise" 列下有多个 "expertise" 数字。不仅仅是该仪器的最大专业知识。

理解解决方案的第一个关键是 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]