2017-02-20 33 views
1

У меня есть база данных, где у нас есть список заданий. Каждая работа находится во многих местах. Пользователь может подать заявку на работу в любом месте. Они могут применяться отдельно к одной и той же работе в разных местах. Каждое приложение задания имеет 4 статуса по мере их продвижения: от 1. Новый до 4. Закрыт.SQL Aggregate Query - Count Nulls

Мне нужно запустить SQL-запрос, чтобы представить сводку каждого задания, в каждом месте и для каждого состояния - количество соответствующих приложений. Так, например

+ ---- + -------- + ------ + ----- + 
| 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.

может кто-нибудь посоветовать о том, как получить 4 статуса для каждой работы в каждом месте, даже если это 0? Я видел различные советы по другим темам о левом соединении, но я пока не добился успеха.

Заранее благодарен!

Edit - Отображение работы Пример таблицы данных

Предполагая Job Locations таблица адресов с идентификационными номерами 5, 6 и 7.

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 подает заявку на Job 1 at Location 5, а их статус приложения - 1.

  • пользователь 1 также применяется для задания 1 на участке 6, и их статус приложения 2.

  • пользователь 2 применяется для задания 1 на участке 5 и их статус приложения 1.

  • Пользователь 2 также применяется для задания 2 на участке 7 и их статуса приложения 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.

+0

, какая версия SQL-сервера вы используете? также покажите ожидаемый результат. –

+0

Только что обновлено, чтобы показать ожидаемый результат выше. SQL Server 2014. –

+0

где вы хотите показать общую сумму? Должен ли быть столбцом? –

ответ

3

Вы были почти там.Поскольку вам нужен весь статус, даже если в Заявке на работу нет корреспонденции, вам необходимо использовать cross join

Кроме того, в этом случае, поскольку для каждого статуса будет «ссылка», вам необходимо использовать СУММ с CASE вместо COUNT.

SQL Fiddle

Сервер 2014 Настройка схемы MS SQL:

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

Запрос 1:

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 

Results:

| 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 | 

EDITED:

Существует способ иметь идентификатор задания, которые не имеют никакого применения. Просто измените JOIN JobApplication на LEFT OUTER JOIN JobApplication и изменить B.JobID в SELECT и пункт GROUP BY с A.JobID

0

Этот тип проблемы, как правило, включает в себя cross join, а затем каким-то образом, чтобы принести в результатах (left join/group by) или подзапроса. Это говорит о том, что:

0

Вы можете добиться тех же результатов без случая, используя счет. Я придумал почти точное решение, как Фабьен. Здесь кросс-соединение является ключевым.

Установка:

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 
0

Фабьен является хорошим, и вы должны отметить, что один в качестве ответа. Но я просто хотел бы добавить, что вы могли бы получить полные суммы, которые вы хотите, используя общее табличное выражение и связанный подзапрос с его запросом

; 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