SQL Server:将不同结果连接到匹配表的单个列中

时间:2019-03-05 15:00:45

标签: sql sql-server concatenation

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

对于给定的输入城市ID,YEAR(Emp表),采用所有不同的SCHOOLID,对于每个SCHOOLID则采用与SCHOOL表不同的等级(所有等级需要合并并显示在单列中);

对于与jobid(JOB)匹配的每个jobid(EMP),对于每个jobname(来自job table),以水平方式获取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 :(得分:0)

我过去也遇到过类似情况。我不得不使用WHILE循环记录,并在字段中连接值。在您的情况下,您可以将记录与上一个记录进行比较,如果它们来自同一城市和学校,则可以在现场进行串联。当然,这取决于表中有多少条记录,因为这种方式的处理不是很快。

答案 1 :(得分:0)

好的,这很丑陋,但是可以工作,并且可以完成您想要的。总计最好在表示层中完成,但是我将主要结果放入了临时表中,以便我们可以从中进行选择并将其与总数进行合并,然后使用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

答案 2 :(得分:0)

某些表值函数可能会有所帮助,首先是连接成绩的函数

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

现在基于parms的计数功能

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