使用表2以表2数据的顺序从表1中检索数据

问题描述 投票:2回答:2

我有两个表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,STATUS CHAR(1));

INSERT INTO JOB(JOBID, JOBNAME) VALUES
        ( 1, 'DEVELOPMENT'),
        (2, 'DEVELOPMENT'),
        (3,'TESTING'),
        (4,'TESTING'),
        (7,'TESTING'),
        (9,'RESEARCH'),
        (8,'HR');

INSERT INTO EMP (EMPID , JOBID, SAL,CITYID,YEAR,STATUS) VALUES
   (  100,1,1000,10,2015,'A'),
   (  200,2,2000,10.2015,'A'),
   (  300,1,2500,20,2015,'E'),
   (  400,3,1000,10,2016,'A'),
   (  500,6,3000,10,2015,'E'),
   (  600,8,1000,30,2015,'A'),
   (  700,8,2000,10,2015,'A'),
   (  800,9,1500,20,2015,'A')
;

我想显示所有的工作名数和平均工资;对于jobname,如果jobid不存在则显示0

对于给定的输入cityid,YEAR和STATUS(Emp表),取每个作业名的所有jobid(来自作业表)并在Emp表中匹配,如果存在显示计数(Emp表中存在的作业数)和其他0作为计数和avgsal。

对于Cityid的2015年10年和20年状态'A',输出应该是这样的

Cityid  jobname        count avg-sal
10       development    2     1500
10       TESTING        0       0
10       RESEARCH       0       0
10       HR             1      2000
10      total           3      1666.66
20      development     0         0
20      Testing         0         0
20      Research        1      1500
20      HR              0         0
20      Total           1     2500
Grand Total             4     1625

我尝试通过加入,但没有正常工作;是否更好地使用连接或光标?

sql sql-server matching
2个回答
1
投票

为了得到你想要的结果,你需要首先CROSS JOIN所有所需的CITYID值的工作,然后你可以LEFT JOINEMP表和SUM工作和平均工资,使用ROLLUP条款得到你的总数:

SELECT C.CITYID,
       j.JOBNAME,
       COUNT(e.CITYID) AS count,
       COALESCE(AVG(e.SAL), 0) AS "avg-sal"
FROM JOB J
CROSS JOIN (SELECT DISTINCT CITYID
            FROM EMP
            WHERE CITYID IN (10, 20)) C
LEFT JOIN EMP e ON e.JOBID = j.JOBID AND e.CITYID = C.CITYID
GROUP BY ROLLUP (C.CITYID, j.JOBNAME)

输出:

CITYID  JOBNAME         count   avg-sal
10      DEVELOPMENT     2       1500
10      HR              1       2000
10      RESEARCH        0       0
10      TESTING         1       1000
10                      4       1500
20      DEVELOPMENT     1       2500
20      HR              0       0
20      RESEARCH        0       0
20      TESTING         0       0
20                      1       2500
                        5       1700

Demo on dbfiddle


1
投票

你可以像下面这样使用GROUP BY ROLLUP

SELECT CASE 
         WHEN cityid IS NOT NULL 
              AND jobname IS NULL THEN 'Total' 
         WHEN cityid IS NULL 
              AND jobname IS NULL THEN 'Grand Total' 
         ELSE Cast(cityid AS VARCHAR(100)) 
       END CityId, 
       jobname, 
       [count], 
       [avg_sal] 
FROM   (SELECT e.cityid, 
               j.jobname, 
               Count(*) [Count], 
               Avg(sal) [Avg_Sal] 
        FROM   job J 
               INNER JOIN emp E 
                       ON e.jobid = j.jobid 
        GROUP  BY rollup ( e.cityid, j.jobname )) t 

Online Demo

编辑:对于所有JOBNAME,你需要使用CROSS JOIN来获得所有组合,如下面的查询。

;WITH CTE AS
    (
    SELECT DISTINCT JOBNAME, E.CITYID, SUM(CASE WHEN J.JOBID=E.JOBID  THEN 1 ELSE NULL END) M
     , AVG(CASE WHEN J.JOBID=E.JOBID AND E.CITYID=E.CITYID THEN SAL ELSE null END) AVG_Sal
        FROM EMP E
        CROSS JOIN JOB J
        GROUP BY JOBNAME, E.CITYID
    ),
     CTE1 AS
    (
    SELECT DISTINCT JOBNAME, E.CITYID
        FROM EMP E
        CROSS JOIN JOB J    
    )
    SELECT
    case when CITYID is not null and JOBNAME is null then 'Total' 
         when cityid is null and JOBNAME is null AND [Avg_Sal] IS NOT NULL then 'Grand Total'
         else cast(cityid as varchar(100))
         end CityId
         ,JOBNAME
         ,[Count]
         ,[Avg_Sal]
     from 
    (
        SELECT e.CITYID,j.JOBNAME,SUM(M) [Count], avg([Avg_Sal]) [Avg_Sal]
         FROM CTE  J
        INNER JOIN  CTE1 E on  E.CITYID=J.CITYID AND J.JOBNAME=E.JOBNAME
        GROUP BY ROLLUP (e.CITYID,j.JOBNAME) 
    ) t

Demo 2

产量

+-------------+-------------+-------+---------+
| CityId      | JOBNAME     | Count | Avg_Sal |
+-------------+-------------+-------+---------+
| 10          | DEVELOPMENT | 2     | 1500    |
+-------------+-------------+-------+---------+
| 10          | HR          | 1     | 2000    |
+-------------+-------------+-------+---------+
| 10          | RESEARCH    | NULL  | NULL    |
+-------------+-------------+-------+---------+
| 10          | TESTING     | 1     | 1000    |
+-------------+-------------+-------+---------+
| Total       | NULL        | 4     | 1500    |
+-------------+-------------+-------+---------+
| 20          | DEVELOPMENT | 1     | 2500    |
+-------------+-------------+-------+---------+
| 20          | HR          | NULL  | NULL    |
+-------------+-------------+-------+---------+
| 20          | RESEARCH    | NULL  | NULL    |
+-------------+-------------+-------+---------+
| 20          | TESTING     | NULL  | NULL    |
+-------------+-------------+-------+---------+
| Total       | NULL        | 1     | 2500    |
+-------------+-------------+-------+---------+
| 30          | DEVELOPMENT | NULL  | NULL    |
+-------------+-------------+-------+---------+
| 30          | HR          | 1     | 1000    |
+-------------+-------------+-------+---------+
| 30          | RESEARCH    | NULL  | NULL    |
+-------------+-------------+-------+---------+
| 30          | TESTING     | NULL  | NULL    |
+-------------+-------------+-------+---------+
| Total       | NULL        | 1     | 1000    |
+-------------+-------------+-------+---------+
| Grand Total | NULL        | 6     | 1600    |
+-------------+-------------+-------+---------+
© www.soinside.com 2019 - 2024. All rights reserved.