如何对 SQL 个创建的列执行聚合

How to perform aggregation to SQL created columns

我在 SQL 服务器中有此数据

Name Nationality Gender
Anonymous Chinese M
Anonymous Russian F
Anonymous German F
Anonymous Chinese F
Anonymous American M
Anonymous German M

我可以 return 由不同值分隔的国籍计数:

SELECT
    Nationality,
    COUNT(*) AS [Nat.Count]  
FROM
    [table1]
GROUP BY
    Nationality
Nationality Nat.Count
Chinese 2
Russian 1
German 2
American 1

我该怎么做才能在底部附加一个“总计”行(见下文)? ...就像 Excel?

中的 AutoSum
Nationality Nat.Count
Chinese 2
Russian 1
German 2
American 1
Total 6

这通常是一项前端工作...需要将其作为查询的一部分来执行有点奇怪。但是如果你必须...

SELECT Nationality, COUNT(*) AS [Nat.Count]  
FROM [table1]
GROUP BY Nationality

UNION ALL

SELECT 'Total', COUNT(*)
FROM [table1]

作为使用 UNION you can use GROUP BY ROLLUP.

的替代方法

这种方法的优点是您不需要重复查询的主体 all-over-again。

因为 ROLLUP 使用 NULL 来忽略 grouping-keys,您需要使用 CTE 或 inner-query 使其适应 'Total', and/or 对其进行排序,使其成为最后一行,如下所示:

DECLARE @tbl AS TABLE (
    Nationality nvarchar(100) NOT NULL,
    Gender      char(1)       NOT NULL
);

INSERT INTO @tbl ( Nationality, Gender )
VALUES
( N'Chinese' , 'M' ),
( N'Russian' , 'F' ),
( N'German'  , 'F' ),
( N'Chinese' , 'F' ),
( N'American', 'M' ),
( N'German'  , 'M' );

-----

WITH counts AS (
    SELECT
        ROW_NUMBER() OVER ( ORDER BY Nationality ) AS r,
        Nationality,
        COUNT(*) AS "Nat.Count"
    FROM
        @tbl
    GROUP BY ROLLUP
        ( Nationality )
)
SELECT
    ISNULL( Nationality, 'Total' ) AS Nationality,
    "Nat.Count"
FROM
    counts
ORDER BY
    /* This puts the 'Total' row last, but sorts all other rows by `Nationality`: */
    CASE WHEN counts.Nationality IS NULL THEN 1 ELSE 0 END,
    counts.r

或者,更简洁:

SELECT
    ISNULL( t.Nationality, 'Total' ) AS Nationality,
    COUNT(*) AS "Nat.Count"
FROM
    @tbl AS t
GROUP BY ROLLUP
    ( t.Nationality )
ORDER BY
    /* This puts the 'Total' row last, but sorts all other rows by `Nationality`: */
    CASE WHEN t.Nationality IS NULL THEN 1 ELSE 0 END,
    t.Nationality;
  • 请注意,GROUP BY ROLLUP 总是 要求 GROUP BY 列列表用括号分隔,即使您只指定一个列名。
    • 所以这行不通:
      GROUP BY ROLLUP
          t.Nationality
      

Fun-fact:GROUP BY ROLLUP 也适用于具有内部标准的聚合函数,因此修改查询以添加按国家/地区细分的性别是微不足道的 and 得到总数:

SELECT
    ISNULL( t.Nationality, 'Total' ) AS Nationality,
    COUNT(*) AS "COUNT( People )",
    COUNT( CASE Gender WHEN 'F' THEN 1 END ) AS "COUNT( Females )",
    COUNT( CASE Gender WHEN 'M' THEN 1 END ) AS "COUNT( Males )",
    COUNT( CASE WHEN Gender NOT IN ( 'F', 'M' ) THEN 1 END ) AS "COUNT( Other )"
FROM
    @tbl AS t
GROUP BY ROLLUP
    ( t.Nationality )
ORDER BY
    /* This puts the 'Total' row last, but sorts all other rows by `Nationality`: */
    CASE WHEN t.Nationality IS NULL THEN 1 ELSE 0 END,
    t.Nationality;

截图证明: