You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQL PIVOT中为列实现“捕获所有其他值”的功能?

如何在SQL PIVOT中将未指定的分组值汇总到统一列中?

问题背景

需要统计指定日期(2023-04-30)下各游戏的有效玩家数(仅UserType=1算作有效玩家),并将结果按玩家数分组转换为单行多列的形式:

  • 玩家数为0、1、2时分别对应0pGames、1pGames、2pGames列
  • 玩家数为其他值时,全部汇总到AllOtherGames列

原查询先计算每个游戏的有效玩家数:

SELECT
    gm.[Id]
    ,SUM(CASE WHEN mbr.[UserType] = 1 THEN 1 ELSE 0 END) AS NbrPlayers
FROM
    dbo.[Game] gm
    LEFT JOIN dbo.[GameMembership] mbr ON gm.[Id] = mbr.[GameId]
WHERE
    CAST(gm.[DateCreated] AS DATE) = CAST('2023-04-30' AS DATE)
GROUP BY
    gm.[Id]

得到的示例结果:

Id                                      NbrPlayers
==================================================
FFA8C1D6-CEB6-4823-B436-18F0417EEBD0    2
E14B2558-F8B4-4660-967C-2EBC452BE881    0
208B46F8-B39D-4BC8-A907-57A07CD0A380    1
76275D64-AFD9-425C-8BD5-9FA770C24AA5    1
EA092967-680B-4EA6-A137-CD9834C51323    2
6C346BA1-1D3D-410A-A1A3-CF0B2F840C0E    1
EC68A93E-996F-4D4E-B443-DE63BD9B9F59    1
06C9A62D-9790-4080-8863-F7F2D0432F67    1
428D6C3F-57AF-4F6C-AE7F-F8C5D10AA6A5    2
DF027EE0-FAA3-4DA2-844A-F94AB6D56C2C    1
C82E60DF-7193-4099-B273-FE497B3002E5    1

使用PIVOT转换为指定列后:

SELECT
    [0] AS [0pGames], [1] AS [1pGames], [2] AS [2pGames]
FROM (
    SELECT
        gm.[Id]
        ,SUM(CASE WHEN mbr.[UserType] = 1 THEN 1 ELSE 0 END) AS NbrPlayers
    FROM
        dbo.[Game] gm
        LEFT JOIN dbo.[GameMembership] mbr ON gm.[Id] = mbr.[GameId]
    WHERE
        CAST(gm.[DateCreated] AS DATE) = CAST('2023-04-30' AS DATE)
    GROUP BY
        gm.[Id]
) x
PIVOT (
    COUNT([Id])
    FOR [NbrPlayers] IN ([0], [1], [2])
) pvt

得到结果:

0pGames    1pGames    2pGames
=============================
1          7          3

但PIVOT无法直接捕获未指定的NbrPlayers值,需要实现将其他值汇总到AllOtherGames列的需求。

解决方案

方法1:在子查询中统一标记非目标值后再PIVOT

通过CASE语句将非0/1/2的玩家数统一标记为AllOther,再进行PIVOT操作:

SELECT
    [0] AS [0pGames], 
    [1] AS [1pGames], 
    [2] AS [2pGames],
    [AllOther] AS [AllOtherGames]
FROM (
    SELECT
        gm.[Id],
        -- 将非0/1/2的玩家数统一标记为AllOther
        CASE 
            WHEN SUM(CASE WHEN mbr.[UserType] = 1 THEN 1 ELSE 0 END) IN (0,1,2)
            THEN CAST(SUM(CASE WHEN mbr.[UserType] = 1 THEN 1 ELSE 0 END) AS VARCHAR(10))
            ELSE 'AllOther'
        END AS PlayerCategory
    FROM
        dbo.[Game] gm
        LEFT JOIN dbo.[GameMembership] mbr ON gm.[Id] = mbr.[GameId]
    WHERE
        CAST(gm.[DateCreated] AS DATE) = CAST('2023-04-30' AS DATE)
    GROUP BY
        gm.[Id]
) x
PIVOT (
    COUNT([Id])
    FOR [PlayerCategory] IN ([0], [1], [2], [AllOther])
) pvt

方法2:使用条件聚合替代PIVOT(推荐)

直接通过外层的条件聚合统计各分类数量,逻辑更直观,无需依赖PIVOT的列限制:

SELECT
    SUM(CASE WHEN NbrPlayers = 0 THEN 1 ELSE 0 END) AS [0pGames],
    SUM(CASE WHEN NbrPlayers = 1 THEN 1 ELSE 0 END) AS [1pGames],
    SUM(CASE WHEN NbrPlayers = 2 THEN 1 ELSE 0 END) AS [2pGames],
    SUM(CASE WHEN NbrPlayers NOT IN (0,1,2) THEN 1 ELSE 0 END) AS [AllOtherGames]
FROM (
    SELECT
        gm.[Id],
        SUM(CASE WHEN mbr.[UserType] = 1 THEN 1 ELSE 0 END) AS NbrPlayers
    FROM
        dbo.[Game] gm
        LEFT JOIN dbo.[GameMembership] mbr ON gm.[Id] = mbr.[GameId]
    WHERE
        CAST(gm.[DateCreated] AS DATE) = CAST('2023-04-30' AS DATE)
    GROUP BY
        gm.[Id]
) x

两种方法都能得到目标结果:

0pGames    1pGames    2pGames    AllOtherGames
==============================================
1          7          3          4

内容的提问来源于stack exchange,提问作者Jez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:07:49