SQL聚合查询-计数为空
我有一个数据库,我们有一个工作列表。每个作业位于1到多个位置。用户可以在任何位置申请工作。他们可以在不同的地点分别申请同一份工作。每个职务申请从1开始有4种状态。新到4。关闭 我需要运行一个SQL查询来显示每个作业、每个位置的摘要,以及每个状态的相关应用程序计数。比如说SQL聚合查询-计数为空,sql,tsql,join,count,aggregate-functions,Sql,Tsql,Join,Count,Aggregate Functions,我有一个数据库,我们有一个工作列表。每个作业位于1到多个位置。用户可以在任何位置申请工作。他们可以在不同的地点分别申请同一份工作。每个职务申请从1开始有4种状态。新到4。关闭 我需要运行一个SQL查询来显示每个作业、每个位置的摘要,以及每个状态的相关应用程序计数。比如说 + ---- + -------- + ------ + ----- + | Job | Location | Status | Count | + ---- + -------- + ------ + ----- + | 1
+ ---- + -------- + ------ + ----- +
| Job | Location | Status | Count |
+ ---- + -------- + ------ + ----- +
| 1000 | 1 | 1 | 7 |
| 1000 | 1 | 2 | 0 |
| 1000 | 1 | 3 | 1 |
| 1000 | 1 | 4 | 1 |
| 1000 | 2 | 1 | 4 |
| 1000 | 2 | 2 | 2 |
| 1000 | 2 | 3 | 0 |
| 1000 | 2 | 4 | 8 |
+ ---- + -------- + ------ + ----- +
此外,我理想地希望将4个状态计数相加,形成同一列表中的总和
这是我到目前为止编写的SQL语句:-
SELECT B.JobID, B.LocationID, B.ApplicationStatusID, COUNT(B.JobID) AS CountOfResults
FROM Job AS A
JOIN JobApplication AS B ON A.JobID = B.JobID
LEFT JOIN JobApplicationStatus AS C ON B.ApplicationStatusID = C.JobApplicationStatusID
WHERE A.BrandID = 1
GROUP BY B.JobID, B.LocationID, B.ApplicationStatusID
它是有效的,除了两件事:-
- 我不确定如何获取总计数(或者我可以稍后在服务器端执行此操作)
- 当计数为0时,它不会显示结果
Job
+ ------ + ---------- + ------------------- +
| Job ID | Job Title | Description |
+ ------ + ---------- + ------------------- +
| 1 | Developer | My Nice Description |
| 2 | Full Stack | Another Description |
+ ------ + ---------- + ------------------- +
Job Location
+ -- + ------ + ----------- +
| ID | Job ID | Location ID |
+ -- + ------ + ----------- +
| 1 | 1 | 5 |
| 2 | 1 | 6 |
| 3 | 2 | 5 |
| 4 | 2 | 6 |
| 5 | 2 | 7 |
+ -- + ------ + ----------- +
Job Application
+ -- + ------- + ------ + ----------- + --------------------- +
| ID | User ID | Job ID | Location ID | Application Status ID |
+ -- + ------- + ------ + ----------- + --------------------- +
| 1 | 1 | 1 | 5 | 1 |
| 2 | 1 | 1 | 6 | 2 |
| 3 | 2 | 1 | 5 | 1 |
| 4 | 2 | 2 | 7 | 4 |
+ -- + ------- + ------ + ----------- + --------------------- +
在“职务申请状态”表中:-
- 用户1在位置5申请作业1,其申请状态为1
- 用户1也在位置6申请作业1,其申请状态为2
- 用户2在位置5申请作业1,其申请状态为1
- 用户2也在位置7申请作业2,其申请状态为4
Result
+ --- + -------- + ------ + ----- +
| Job | Location | Status | Count |
+ --- + -------- + ------ + ----- +
| 1 | 5 | 1 | 2 |
| 1 | 5 | 2 | 0 |
| 1 | 5 | 3 | 0 |
| 1 | 5 | 4 | 0 |
| 1 | 6 | 1 | 0 |
| 1 | 6 | 2 | 1 |
| 1 | 6 | 3 | 0 |
| 1 | 6 | 4 | 0 |
+ --- + -------- + ------ + ----- +
以此类推,应显示0。计数是处于该状态编号的工作申请的计数。有4个状态号,它们在一个名为JobApplicationStatus的联接表中设置。您就快到了。因为即使在求职申请中没有对应关系,您也需要所有状态,所以您需要使用 此外,在这种情况下,因为每个状态都有一个“链接”,所以您需要在案例场景中使用SUM而不是COUNT MS SQL Server 2014架构设置:
CREATE TABLE Job
([JobID] int, [JobTitle] varchar(10), [Description] varchar(23), [BrandID] int)
;
INSERT INTO Job
([JobID], [JobTitle], [Description], [BrandID])
VALUES
(1, 'Developer', 'My nice description', 1),
(2, 'Full Stack', 'Another job description', 1)
;
CREATE TABLE JobApplication
([ID] int, [UserID] int, [JobID] int, [LocationID] int, [ApplicationStatusID] int)
;
INSERT INTO JobApplication
([ID], [UserID], [JobID], [LocationID], [ApplicationStatusID])
VALUES
(1, 1, 1, 5, 1),
(2, 1, 1, 6, 2),
(3, 2, 1, 5, 1),
(4, 2, 2, 7, 4)
;
CREATE TABLE JobApplicationStatus
([JobApplicationStatusID] int, [Description] varchar(11))
;
INSERT INTO JobApplicationStatus
([JobApplicationStatusID], [Description])
VALUES
(1, 'New'),
(2, 'In Progress'),
(3, 'Hold'),
(4, 'Closed')
;
SELECT B.JobID, B.LocationID, C.JobApplicationStatusID,
sum(case when B.ApplicationStatusID = C.JobApplicationStatusID then 1 else 0 end) AS CountOfResults
FROM Job AS A
JOIN JobApplication AS B ON A.JobID = B.JobID
cross join JobApplicationStatus AS C
WHERE A.BrandID = 1
GROUP BY B.JobID, B.LocationID, C.JobApplicationStatusID
| JobID | LocationID | JobApplicationStatusID | CountOfResults |
|-------|------------|------------------------|----------------|
| 1 | 5 | 1 | 2 |
| 1 | 5 | 2 | 0 |
| 1 | 5 | 3 | 0 |
| 1 | 5 | 4 | 0 |
| 1 | 6 | 1 | 0 |
| 1 | 6 | 2 | 1 |
| 1 | 6 | 3 | 0 |
| 1 | 6 | 4 | 0 |
| 2 | 7 | 1 | 0 |
| 2 | 7 | 2 | 0 |
| 2 | 7 | 3 | 0 |
| 2 | 7 | 4 | 1 |
查询1:
CREATE TABLE Job
([JobID] int, [JobTitle] varchar(10), [Description] varchar(23), [BrandID] int)
;
INSERT INTO Job
([JobID], [JobTitle], [Description], [BrandID])
VALUES
(1, 'Developer', 'My nice description', 1),
(2, 'Full Stack', 'Another job description', 1)
;
CREATE TABLE JobApplication
([ID] int, [UserID] int, [JobID] int, [LocationID] int, [ApplicationStatusID] int)
;
INSERT INTO JobApplication
([ID], [UserID], [JobID], [LocationID], [ApplicationStatusID])
VALUES
(1, 1, 1, 5, 1),
(2, 1, 1, 6, 2),
(3, 2, 1, 5, 1),
(4, 2, 2, 7, 4)
;
CREATE TABLE JobApplicationStatus
([JobApplicationStatusID] int, [Description] varchar(11))
;
INSERT INTO JobApplicationStatus
([JobApplicationStatusID], [Description])
VALUES
(1, 'New'),
(2, 'In Progress'),
(3, 'Hold'),
(4, 'Closed')
;
SELECT B.JobID, B.LocationID, C.JobApplicationStatusID,
sum(case when B.ApplicationStatusID = C.JobApplicationStatusID then 1 else 0 end) AS CountOfResults
FROM Job AS A
JOIN JobApplication AS B ON A.JobID = B.JobID
cross join JobApplicationStatus AS C
WHERE A.BrandID = 1
GROUP BY B.JobID, B.LocationID, C.JobApplicationStatusID
| JobID | LocationID | JobApplicationStatusID | CountOfResults |
|-------|------------|------------------------|----------------|
| 1 | 5 | 1 | 2 |
| 1 | 5 | 2 | 0 |
| 1 | 5 | 3 | 0 |
| 1 | 5 | 4 | 0 |
| 1 | 6 | 1 | 0 |
| 1 | 6 | 2 | 1 |
| 1 | 6 | 3 | 0 |
| 1 | 6 | 4 | 0 |
| 2 | 7 | 1 | 0 |
| 2 | 7 | 2 | 0 |
| 2 | 7 | 3 | 0 |
| 2 | 7 | 4 | 1 |
:
CREATE TABLE Job
([JobID] int, [JobTitle] varchar(10), [Description] varchar(23), [BrandID] int)
;
INSERT INTO Job
([JobID], [JobTitle], [Description], [BrandID])
VALUES
(1, 'Developer', 'My nice description', 1),
(2, 'Full Stack', 'Another job description', 1)
;
CREATE TABLE JobApplication
([ID] int, [UserID] int, [JobID] int, [LocationID] int, [ApplicationStatusID] int)
;
INSERT INTO JobApplication
([ID], [UserID], [JobID], [LocationID], [ApplicationStatusID])
VALUES
(1, 1, 1, 5, 1),
(2, 1, 1, 6, 2),
(3, 2, 1, 5, 1),
(4, 2, 2, 7, 4)
;
CREATE TABLE JobApplicationStatus
([JobApplicationStatusID] int, [Description] varchar(11))
;
INSERT INTO JobApplicationStatus
([JobApplicationStatusID], [Description])
VALUES
(1, 'New'),
(2, 'In Progress'),
(3, 'Hold'),
(4, 'Closed')
;
SELECT B.JobID, B.LocationID, C.JobApplicationStatusID,
sum(case when B.ApplicationStatusID = C.JobApplicationStatusID then 1 else 0 end) AS CountOfResults
FROM Job AS A
JOIN JobApplication AS B ON A.JobID = B.JobID
cross join JobApplicationStatus AS C
WHERE A.BrandID = 1
GROUP BY B.JobID, B.LocationID, C.JobApplicationStatusID
| JobID | LocationID | JobApplicationStatusID | CountOfResults |
|-------|------------|------------------------|----------------|
| 1 | 5 | 1 | 2 |
| 1 | 5 | 2 | 0 |
| 1 | 5 | 3 | 0 |
| 1 | 5 | 4 | 0 |
| 1 | 6 | 1 | 0 |
| 1 | 6 | 2 | 1 |
| 1 | 6 | 3 | 0 |
| 1 | 6 | 4 | 0 |
| 2 | 7 | 1 | 0 |
| 2 | 7 | 2 | 0 |
| 2 | 7 | 3 | 0 |
| 2 | 7 | 4 | 1 |
编辑:
DECLARE @Job TABLE(
JobId tinyint,
JobTitle varchar(55),
JobDescription varchar(55)
);
INSERT INTO @Job
VALUES
(1,'Developer','My nice description'),
(2,'Full Stack','Another job description');
DECLARE @JobLocation TABLE(
Id tinyint,
JobId tinyint,
LocationId tinyint
);
INSERT INTO @JobLocation
VALUES
(1,1,5),
(2,1,6),
(3,2,5),
(4,2,6),
(5,2,7);
DECLARE @JobApplication TABLE(
Id tinyint,
UserId tinyint,
JobId tinyint,
LocationId tinyint,
ApplicationStatusId tinyint
);
INSERT INTO @JobApplication
VALUES
(1,1,1,5,1),
(2,1,1,6,2),
(3,2,1,5,1),
(4,2,2,7,4);
--End sample data
DECLARE @JobStatus TABLE(
StatusId int,
ApplicationStatus varchar(55)
);
INSERT INTO @JobStatus
VALUES
(1, 'Application Received'),
(2, 'Application Review Started'),
(3, 'Application In Final Review'),
(4, 'Application Closed');
select job.JobId,
jl.LocationId,
js.StatusId,
count(ja.Id) as StatusCount
from @Job job
cross apply @JobStatus js
inner join @JobLocation jl on job.JobId = jl.JobId
left join @JobApplication ja on job.JobId = ja.JobId
and ja.LocationId = jl.LocationId
and ja.ApplicationStatusId = js.StatusId
where job.JobId = 1 -- filter for single job
group by job.jobId, jl.LocationId, js.StatusId
order by job.JobId, jl.LocationId, js.StatusId
有一种方法可以使作业id没有应用程序。只需将
JOIN-JobApplication
更改为LEFT-OUTER-job-JobApplication
,并在SELECT
中更改B.JobID
,以及带有A.JobID的GROUP BY BY
子句的GROUP>(左连接
/分组依据
)或子查询。这建议:
SELECT j.JobID, l.LocationID, ja.ApplicationStatusID,
COUNT(ja.JobID) AS CountOfResults
FROM Job j CROSS JOIN
Location l LEFT JOIN
JobApplication ja
ON j.JobID = jb.JobID AND
l.LocationId = jb.LocationId
WHERE j.BrandID = 1
GROUP BY j.JobID, l.LocationID, ja.ApplicationStatusID
使用count可以在没有案例的情况下获得相同的结果。我提出了与Fabien几乎完全相同的解决方案。交叉连接是这里的关键
设置:
DECLARE @Job TABLE(
JobId tinyint,
JobTitle varchar(55),
JobDescription varchar(55)
);
INSERT INTO @Job
VALUES
(1,'Developer','My nice description'),
(2,'Full Stack','Another job description');
DECLARE @JobLocation TABLE(
Id tinyint,
JobId tinyint,
LocationId tinyint
);
INSERT INTO @JobLocation
VALUES
(1,1,5),
(2,1,6),
(3,2,5),
(4,2,6),
(5,2,7);
DECLARE @JobApplication TABLE(
Id tinyint,
UserId tinyint,
JobId tinyint,
LocationId tinyint,
ApplicationStatusId tinyint
);
INSERT INTO @JobApplication
VALUES
(1,1,1,5,1),
(2,1,1,6,2),
(3,2,1,5,1),
(4,2,2,7,4);
--End sample data
DECLARE @JobStatus TABLE(
StatusId int,
ApplicationStatus varchar(55)
);
INSERT INTO @JobStatus
VALUES
(1, 'Application Received'),
(2, 'Application Review Started'),
(3, 'Application In Final Review'),
(4, 'Application Closed');
select job.JobId,
jl.LocationId,
js.StatusId,
count(ja.Id) as StatusCount
from @Job job
cross apply @JobStatus js
inner join @JobLocation jl on job.JobId = jl.JobId
left join @JobApplication ja on job.JobId = ja.JobId
and ja.LocationId = jl.LocationId
and ja.ApplicationStatusId = js.StatusId
where job.JobId = 1 -- filter for single job
group by job.jobId, jl.LocationId, js.StatusId
order by job.JobId, jl.LocationId, js.StatusId
查询:
DECLARE @Job TABLE(
JobId tinyint,
JobTitle varchar(55),
JobDescription varchar(55)
);
INSERT INTO @Job
VALUES
(1,'Developer','My nice description'),
(2,'Full Stack','Another job description');
DECLARE @JobLocation TABLE(
Id tinyint,
JobId tinyint,
LocationId tinyint
);
INSERT INTO @JobLocation
VALUES
(1,1,5),
(2,1,6),
(3,2,5),
(4,2,6),
(5,2,7);
DECLARE @JobApplication TABLE(
Id tinyint,
UserId tinyint,
JobId tinyint,
LocationId tinyint,
ApplicationStatusId tinyint
);
INSERT INTO @JobApplication
VALUES
(1,1,1,5,1),
(2,1,1,6,2),
(3,2,1,5,1),
(4,2,2,7,4);
--End sample data
DECLARE @JobStatus TABLE(
StatusId int,
ApplicationStatus varchar(55)
);
INSERT INTO @JobStatus
VALUES
(1, 'Application Received'),
(2, 'Application Review Started'),
(3, 'Application In Final Review'),
(4, 'Application Closed');
select job.JobId,
jl.LocationId,
js.StatusId,
count(ja.Id) as StatusCount
from @Job job
cross apply @JobStatus js
inner join @JobLocation jl on job.JobId = jl.JobId
left join @JobApplication ja on job.JobId = ja.JobId
and ja.LocationId = jl.LocationId
and ja.ApplicationStatusId = js.StatusId
where job.JobId = 1 -- filter for single job
group by job.jobId, jl.LocationId, js.StatusId
order by job.JobId, jl.LocationId, js.StatusId
Fabien的答案很好,你应该把这个标记为答案,但我只想补充一点,你可以通过使用一个公共表表达式和一个与他的查询相关的子查询得到你想要的总和
; with
StatusCounts as (
SELECT B.JobID, B.LocationID, C.JobApplicationStatusID,
sum(case when B.ApplicationStatusID = C.JobApplicationStatusID then 1 else 0 end) AS CountOfResults
FROM Job AS A
JOIN JobApplication AS B ON A.JobID = B.JobID
cross join JobApplicationStatus AS C
WHERE A.BrandID = 1
GROUP BY B.JobID, B.LocationID, C.JobApplicationStatusID
)
select *,
(select SUM(CountOfResults)
from StatusCounts SQ
where SQ.JobID = D.JobID
and SQ.LocationID = D.LocationID
) as TotalSum
from StatusCounts D
您使用的是哪个版本的sql server?还请显示预期的输出。刚刚更新以显示上面的预期输出。sql server 2014。您想在哪里显示总和?这应该是一列吗?您的意思是没有JobApplication的作业没有计数?然后使用外部联接:从作业作为左联接JobApplication
。a边注意:没有意义的别名只会混淆。请改用有意义的缩写,例如j
用于Job
,a
或ja
用于JobApplication等。