Значения результатов SQL по горизонтали

#sql #sql-server

#sql #sql-сервер

Вопрос:

У меня есть две таблицы 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');
  

Для заданного входного идентификатора города, ГОДА (таблица Emp) возьмите все идентификаторы вакансий для каждого имени вакансии (из таблицы job ) и сопоставьте в таблице Emp, если существует отображение count (количество идентификаторов вакансий, присутствующих в таблице Emp) каждого пола (мужского и женского) для штатов NY, NJ, CA в горизонтальном виде; а также итоговые значения. если совпадения нет, отобразите 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     
  

Как получить результаты в горизонтальном виде ..?

Комментарии:

1. Если это фиксированное количество состояний, вы можете использовать выражения case для выполнения условной агрегации. Если это неизвестное / динамическое количество состояний, проверьте сводную таблицу 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-запроса и использовать проверку ВЫПОЛНЕНИЯ по этой ссылке.

Другим способом вы можете использовать сводную проверку по этой ссылке :

Ответ №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 предложении.

Здесь находится db<>fiddle.