SQL Server: объединить отдельные результаты в один столбец из сопоставленной таблицы - PullRequest
1 голос
/ 05 марта 2019

у меня 3 таблицы EMP, SCHOOL, JOB; структура и значения таковы:

CREATE TABLE SCHOOL
(
    SCHOOLID CHAR(2),
    STUDENTID  SMALLINT,
    GRADE      CHAR(4)    
);

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

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

INSERT INTO SCHOOL(SCHOOLID, STUDENTID, GRADE) 
VALUES ('S1', 10, 'PKG'),
       ('S1', 20, 'LKG'),
       ('S2', 10, 'PKG'),
       ('S2', 20, 'LKG'),
       ('S2', 30, '1ST'),
       ('S2', 30, '2ND');

INSERT INTO JOB(JOBID, JOBNAME) 
VALUES (1, 'PRINCIPAL'),
       (2, 'ASST PRINCIPAL'),
       (3, 'TEACHING'),
       (4, 'CLERICAL'),
       (7, 'HELPER');

INSERT INTO EMP (EMPID , JOBID, SAL, CITYID, YEAR, SCHOOLID, SEX, EMPCAT) 
VALUES (100, 1, 1000, 10, 2015, 'S1', 'M', 'A'),
       (200, 2, 2000, 10, 2015, 'S1', 'M', 'B'),
       (300, 1, 2500, 10, 2015, 'S1', 'F', 'A'),
       (400, 1, 1000, 10, 2015, 'S2', 'M', 'B'),
       (500, 1, 3000, 10, 2015, 'S2', 'F', 'A'),
       (600, 3, 1000, 10, 2015, 'S2', 'M', 'A'),
       (700, 3, 2000, 20, 2015, 'S2', 'F', 'A');

Для заданного входного cityid, YEAR (таблица Emp), взять все отдельные SCHOOLID и для каждого SCHOOLID взять отдельную оценку из таблицы SCHOOL (все оценки должны быть объединены и отображены в одном столбце);

И для каждого идентификатора вакансии (ПУОС), который совпадает с идентификатором вакансии (JOB), для каждого имени работы (из таблицы вакансий) получайте подсчеты для каждого пола (мужчины и женщины) для EMPCAT 'A', 'B' по горизонтали. ; и итоги также.

Вывод должен быть таким:

CITYID  SCHOOLID  GRADES              Jobname                  Male           FEMALE              TOTAL
                                                             A    B           A    B          
10      S1        PKG-LKG            PRINCIPAL               1    0           1    0                 2
10      S1        PKG-LKG            ASST PRINCIPAL          0    1           0    0                 1
10      S2        PKG-LKG-1ST        PRINCIPAL               0    1           1    0                 2
10      S2        PKG-LKG-1ST        TEACHING                1    0           0    0                 1
TOTAL                                                        1    2           2    0                 6

20      S2        PKG-LKG-1ST        TEACHING                1    0           0    0                 1     
TOTAL                                                        1    0           0    0                 1

Как объединить школьные оценки в один столбец и результаты EMPCAT по горизонтали ..?

Ответы [ 3 ]

0 голосов
/ 05 марта 2019

ОК, это безобразно, но работает, и делает то, что вы хотите. Суммирование было бы лучше выполнить на уровне презентации, но я поместил первичные результаты во временную таблицу, чтобы мы могли затем выбрать из нее и объединить ее с итогами, а затем заказать, используя CITYID и OrderKey, чтобы получить нужную презентацию.

Declare @Results as table
(orderkey int, cityid int, schoolid varchar(5), Grades varchar(100), Jobname varchar(100), Male_A int, Male_B int, Female_A int, Female_B int)

INSERT INTO @results
Select DISTINCT 1 as orderkey, CITYID, e.schoolid , g.grades, j.JOBNAME, 
empcount.scount as Male_A, empcountB.scountB as Male_B, empcountFA.scountFA as Female_A, empcountFB.scountFB as Female_B

from emp e 

left join job j on e.JOBID=j.JOBID

outer apply (select STUFF((Select ',' + GRADE from school s where s.SCHOOLID=e.SCHOOLID FOR XML PATH('')),1,1,'' ) as grades) g
outer apply (select  count(sex) as  scount from emp ee where ee.jobid=e.jobid and sex='M' and ee.empcat='A'
and (select STUFF((Select ',' + GRADE from school s where s.SCHOOLID=ee.SCHOOLID FOR XML PATH('')),1,1,'' ))=g.grades
) empcount
outer apply (select  count(sex) as  scountB from emp ee where ee.jobid=e.jobid and sex='M' and ee.empcat='B'
and (select STUFF((Select ',' + GRADE from school s where s.SCHOOLID=ee.SCHOOLID FOR XML PATH('')),1,1,'' ))=g.grades
) empcountB
outer apply (select  count(sex) as  scountFA from emp ee where ee.jobid=e.jobid and sex='F' and ee.empcat='A'
and (select STUFF((Select ',' + GRADE from school s where s.SCHOOLID=ee.SCHOOLID FOR XML PATH('')),1,1,'' ))=g.grades
) empcountFA
outer apply (select  count(sex) as  scountFB from emp ee where ee.jobid=e.jobid and sex='F' and ee.empcat='B'
and (select STUFF((Select ',' + GRADE from school s where s.SCHOOLID=ee.SCHOOLID FOR XML PATH('')),1,1,'' ))=g.grades
) empcountFB

Select * from @results

UNION ALL

Select DISTINCT 99,CITYID, '' ,'TOTAL', '', 
sum(Male_A) as Male_A, sum(Male_B) as Male_B, sum(Female_A) as Female_A, sum(Female_B) as Female_B
from @results
group by CITYID

ORDER BY CITYID, orderkey
0 голосов
/ 05 марта 2019

Некоторые табличные функции могут помочь, начните с функции для объединения оценок

ALTER FUNCTION [dbo].[GetSchoolGrades] ()
RETURNS 
@school_grades table
(
    SCHOOLID  CHAR(2),
    GRADES    CHAR(24)    
)
AS
BEGIN
    with cte_grades (SCHOOLID, GRADES) as
    (
        select a1.SCHOOLID, 
               (
                select rtrim(x1.GRADE) + '-'
                from   SCHOOL x1
                where  x1.SCHOOLID = a1.SCHOOLID
                group  by x1.GRADE
                for    xml path ('')
            ) as GRADES
        from   SCHOOL a1
        group  by a1.SCHOOLID
    ) 
    insert into @school_grades(SCHOOLID, GRADES)
    select SCHOOLID, LEFT(GRADES, len(GRADES) -1) as GRADES
    from   cte_grades;
    RETURN 
END

Теперь функция для подсчета, основанная на параметрах

ALTER FUNCTION [dbo].[GetEmpCatCounts]
(
    @JOBID     SMALLINT,  
    @SCHOOLID  CHAR(2),
    @SEX       CHAR(1),
    @EMPCAT    CHAR(2)
)
RETURNS int
AS
BEGIN
    return (
       select count(*) from EMP m1 
       where  m1.JOBID    = @JOBID
       and    m1.SCHOOLID = @SCHOOLID
       and    m1.SEX      = @SEX
       and    m1.EMPCAT   = @EMPCAT
    )

END

Свяжите все вместе вот так

select a1.CITYID,
       a1.SCHOOLID,
       g1.GRADES,
       j1.JOBNAME,
       (select dbo.GetEmpCatCounts(a1.JOBID, a1.SCHOOLID, 'M', 'A')) as EMPCNT_MALE_A,
       (select dbo.GetEmpCatCounts(a1.JOBID, a1.SCHOOLID, 'M', 'B')) as EMPCNT_MALE_B,
       (select dbo.GetEmpCatCounts(a1.JOBID, a1.SCHOOLID, 'F', 'A')) as EMPCNT_FEMALE_A,
       (select dbo.GetEmpCatCounts(a1.JOBID, a1.SCHOOLID, 'F', 'B')) as EMPCNT_FEMALE_B
from   EMP  a1
join   JOB  j1 
on     a1.JOBID = j1.JOBID
join   GetSchoolGrades() g1 
on     a1.SCHOOLID = g1.SCHOOLID
group  by a1.CITYID,
       a1.JOBID,
       a1.SCHOOLID,
       g1.GRADES,
       j1.JOBNAME
order  by a1.CITYID,
       a1.SCHOOLID,
       a1.JOBID,
       g1.GRADES
0 голосов
/ 05 марта 2019

Я сталкивался с подобной ситуацией в прошлом.Мне пришлось зациклить записи, используя WHILE и объединить значения в поле.В вашем случае вы бы сравнили запись с предыдущей, и если они принадлежат одному и тому же городу и школе, вы выполните конкатенацию на месте.Конечно, это зависит от того, сколько записей у вас в таблицах, потому что обработка не очень быстрая.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...