【问题标题】:SQL Results values in horizontal way水平方式的 SQL 结果值
【发布时间】:2026-01-13 04:05:02
【问题描述】:

我有两张表 JOB 和 EMP;结构和值是这样的:

 CREATE TABLE JOB 
(
    JOBID SMALLINT UNIQUE NOT NULL,
    JOBNAME CHAR(15)
);

CREATE TABLE EMP
(
    EMPID SMALLINT, 
    JOBID SMALLINT, 
    SAL SMALLINT, 
    CITYID SMALLINT,
    YEAR SMALLINT,
    SEX  CHAR(1),
    STATE CHAR(2)
);

INSERT INTO JOB(JOBID, JOBNAME) 
VALUES (1, 'DEVELOPMENT'),
       (2, 'DEVELOPMENT'),
       (3, 'TESTING'),
       (4, 'TESTING'),
       (7, 'TESTING'),
       (8, 'HR'),
       (10,  'RESEARCH');

INSERT INTO EMP (EMPID , JOBID, SAL, CITYID, YEAR, SEX,STATE) 
VALUES (100, 1, 1000, 10, 2015, 'M','NY'),
       (200, 2, 2000, 10, 2015, 'M','NJ'),
       (300, 1, 2500, 20, 2015, 'F','NY'),
       (400, 3, 1000, 10, 2015, 'M','CA'),
       (500, 6, 3000, 10, 2015, 'F','NJ'),
       (600, 8, 1000, 30, 2015, 'M','CA'),
       (700, 8, 2000, 10, 2015, 'F','NY'),
       (800, 9, 1500, 10, 2015, 'F','CA');

对于给定的输入 cityid , YEAR (Emp表),获取每个jobname的所有jobids(来自job table)并在Emp表中匹配,如果存在则显示每个性别(男性)的计数(Emp表中存在的jobids计数)和女性)以横向方式代表纽约州、新泽西州、加利福尼亚州;和总数。如果没有匹配显示0。

输出应该是这样的:

Jobname                  Male           FEMALE              TOTAL
                    NY   NJ   CA      NY   NJ   CA 

Development         1     1   0       1    0    0             3
TESTING             0     0   1       0    0    0             1
HR                  0     0   1       1    0    0             2
RESEARCH            0     0   0       0    0    0             0
TOTAL               1     1   2       2    0    0             6     

如何以水平方式获得结果..?

【问题讨论】:

  • 如果是固定数量的状态,您可以使用 case 表达式进行条件聚合。它是未知/动态数量的状态,请查看 SQL Server 的 PIVOT。

标签: sql sql-server


【解决方案1】:

你好,我认为这可以使用:

 CREATE TABLE #JOB 
(
    JOBID SMALLINT UNIQUE NOT NULL,
    JOBNAME CHAR(15)
);

CREATE TABLE #EMP
(
    EMPID SMALLINT, 
    JOBID SMALLINT, 
    SAL SMALLINT, 
    CITYID SMALLINT,
    YEAR SMALLINT,
    SEX  CHAR(1),
    STATE CHAR(2)
);

INSERT INTO #JOB(JOBID, JOBNAME) 
VALUES (1, 'DEVELOPMENT'),
       (2, 'DEVELOPMENT'),
       (3, 'TESTING'),
       (4, 'TESTING'),
       (7, 'TESTING'),
       (8, 'HR'),
       (10, 'RESEARCH');

INSERT INTO #EMP (EMPID , JOBID, SAL, CITYID, YEAR, SEX,STATE) 
VALUES (100, 1, 1000, 10, 2015, 'M','NY'),
       (200, 2, 2000, 10, 2015, 'M','NJ'),
       (300, 1, 2500, 20, 2015, 'F','NY'),
       (400, 3, 1000, 10, 2015, 'M','CA'),
       (500, 6, 3000, 10, 2015, 'F','NJ'),
       (600, 8, 1000, 30, 2015, 'M','CA'),
       (700, 8, 2000, 10, 2015, 'F','NY'),
       (800, 9, 1500, 10, 2015, 'F','CA');



    SELECT * FROM #JOB;

    SELECT * FROM #EMP;


    SELECT J.JOBNAME, 
        SUM(CASE WHEN E.SEX = 'M' AND STATE = 'NY' THEN 1 ELSE 0 END) AS 'Male_NY',
        SUM(CASE WHEN E.SEX = 'M' AND STATE = 'NJ' THEN 1 ELSE 0 END) AS 'Male_NJ',
        SUM(CASE WHEN E.SEX = 'M' AND STATE = 'CA' THEN 1 ELSE 0 END) AS 'Male_CA',
        SUM(CASE WHEN E.SEX = 'F' AND STATE = 'NY' THEN 1 ELSE 0 END) AS 'Female_NY',
        SUM(CASE WHEN E.SEX = 'F' AND STATE = 'NJ' THEN 1 ELSE 0 END) AS 'Female_NJ',
        SUM(CASE WHEN E.SEX = 'F' AND STATE = 'CA' THEN 1 ELSE 0 END) AS 'Female_CA',
        COUNT(*) AS 'Total'
    FROM #EMP E
    JOIN #JOB J ON E.JOBID = J.JOBID
    GROUP BY J.JOBNAME


    DROP TABLE #JOB;

    DROP TABLE #EMP;

但是,如果您有其他一些状态和性别,则它是静态模式,您必须使用动态 SQL 查询来构建它,并在此链接上使用 EXECUTE 检查。

您可以在此链接上使用 PIVOT 检查的其他方式:

【讨论】:

    【解决方案2】:

    首先,SQL 查询不支持多级标头。您可以有复杂的标题字符串,但不能有多个级别。

    其次,您需要没有员工的行。

    第三,你想要一个总行。

    所以,你需要一个外连接:

    SELECT COALESCE(J.JOBNAME, 'TOTAL') as JobName,
           SUM(CASE WHEN E.SEX = 'M' AND E.STATE = 'NY' THEN 1 ELSE 0 END) AS Male_NY,
           SUM(CASE WHEN E.SEX = 'M' AND E.STATE = 'NJ' THEN 1 ELSE 0 END) AS Male_NJ,
           SUM(CASE WHEN E.SEX = 'M' AND E.STATE = 'CA' THEN 1 ELSE 0 END) AS Male_CA,
           SUM(CASE WHEN E.SEX = 'F' AND E.STATE = 'NY' THEN 1 ELSE 0 END) AS Female_NY,
           SUM(CASE WHEN E.SEX = 'F' AND E.STATE = 'NJ' THEN 1 ELSE 0 END) AS Female_NJ,
           SUM(CASE WHEN E.SEX = 'F' AND E.STATE = 'CA' THEN 1 ELSE 0 END) AS Female_CA
    FROM JOB J LEFT JOIN
         EMP E
         ON E.JOBID = J.JOBID AND
            E.YEAR = @YEAR AND
            E.CITYID = @CITYID
    GROUP BY GROUPING SETS ( (J.JOBNAME), () );
    

    如果您想要所有年份/城市的数据,请删除 ON 子句中的条件。

    Here 是一个 dbfiddle。

    【讨论】: