【问题标题】:SQL Server : concatenate distinct results into single column from matched tableSQL Server:将不同的结果连接到匹配表中的单个列中
【发布时间】:2019-07-27 02:13:00
【问题描述】:

我有 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 表中获取不同的等级(所有等级需要连接并显示在单列中);

对于每个与 ​​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 结果连接起来..?

【问题讨论】:

  • 使用 SQL SERVER
  • 使用一些报告工具或在客户端代码中处理不是更好吗?
  • 可能会更好,但需要查询
  • 您使用的是什么版本的 SQL Server?到目前为止,您尝试过什么?

标签: sql sql-server concatenation


【解决方案1】:

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

【讨论】:

  • 这更适合作为评论而不是答案
  • 你是警察吗?
  • 这不是一个讨论论坛,我相信答案应该更准确地说明问题是如何解决的。
【解决方案2】:

一些表值函数可能会有所帮助,从连接成绩的函数开始

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

【讨论】:

    【解决方案3】:

    好的,这很丑陋,但它可以工作,并且可以满足您的需求。在表示层中进行总计会更好,但我已将主要结果放入一个临时表中,以便我们可以从中选择并将其与总计联合,然后使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-17
      • 2012-02-03
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多