SQL以水平方式生成值

SQL以水平方式生成值,sql,sql-server,Sql,Sql Server,我有两张工作表和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), STA

我有两张工作表和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');
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     
对于给定的输入cityid,YEAR(Emp表),获取每个jobname(来自job表)的所有JobID,并在Emp表中进行匹配,如果存在,则以水平方式显示NY、NJ、CA州的每个性别(男性和女性)的计数(Emp表中存在的JobID计数);还有总数。如果没有匹配项,则显示0

输出应如下所示:

 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');
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     

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

嗨,我认为这可以使用:

 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查询构建此模式,并在此链接处使用执行检查

在该链接上使用透视检查的其他方法:


嗨,我认为这可以使用:

 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查询构建此模式,并在此链接处使用执行检查

在该链接上使用透视检查的其他方法:


首先,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
子句中的条件


是一个dbfiddle。

首先,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
子句中的条件


是一个dbfiddle。

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