2016-10-24 2 views
0

У меня есть две таблицы, сотрудники и сотрудники. Я пытаюсь выполнить SQL-запрос, чтобы получить сумму того, сколько времени на отпуск у каждого сотрудника и его текущего баланса на сегодняшний день. Вот мой текущий SQL-запрос:SQL-запрос в запросе SQL по сумме

SELECT 
    e.PIN, 
    e.FirstName, 
    e.LastName, 
    e.Uniform, 
    e.AL_Cap, 
    ev.Value AS '10/1 Balance', 
    (SELECT 
     SUM(value) 
    FROM EmployeeVacations 
    WHERE CreationDate >= '2016-10-01' 
    AND Vacation_Type = 'Taken' 
    AND Vacation_Kind = 'AL' 
    AND EmployeeId = 13) 
    AS Taken 
FROM employees e, 
     EmployeeVacations ev 
WHERE e.Id = ev.EmployeeId 
AND ev.IsHistory = 0 
AND ev.Vacation_Type = 'Forward' 
AND ev.Vacation_Kind = 'AL' 
AND EmployeeId = 13 
ORDER BY e.LastName, e.FirstName 

Это работает, если я выбираю одного сотрудника. Если я удалю «where EmployeeId = 13», я получаю список всех сотрудников с суммой всех каникул каждого в каждой строке (например, 1300 часов). Как я сломаю его, чтобы он показывал только «Взятый для каждого сотрудника»?

+0

В зависимости от того, какую версию SQL-сервера вы используете, это может быть обработано с помощью оконной функции. – SQLUser44

+3

Вы должны использовать явные соединения - это гораздо более разборчиво. – scsimon

+0

Вы показываете список записей завещания сотрудника, каждый вместе с суммой взятого на себя работника. Желательно? Или вы предпочитаете, чтобы сумма форварда сотрудника тоже составляла, т. Е. Только одна строка результата на одного сотрудника? –

ответ

1

Просто угадать, что вы также можете сумму, а не отдельных записей вперед ... Вот запрос, который агрегирует EmployeeVacations за EmployeeId:

select 
    e.pin, 
    e.firstname, 
    e.lastname, 
    e.uniform, 
    e.al_cap, 
    ev.forward_sum as "10/1 balance", 
    ev.taken_sum as taken 
from employee e 
left join 
(
    select  
    employeeid, 
    sum(case when vacation_type = 'Forward' 
      and ishistory = 0 then value else 0 end) as forward_sum, 
    sum(case when vacation_type = 'Taken' 
      and creationdate >= '20161001' then value else 0 end) as taken_sum, 
    from employeevacations 
    where vacation_kind = 'AL' 
    group by employeeid 
) ev on ev.employeeid = e.employeeid 
order by e.lastname, e.firstname; 

Пожалуйста ...

  • использования явные объединения вместо разделенных запятыми соединений до 1992 года для удобства чтения и для менее подверженных ошибкам.
  • использовать двойные кавычки для псевдонимов; одинарные кавычки для строковых литералов.
  • использовать 'yyyymmdd' для дат; это поддерживаемый формат даты в SQL Server.
+0

Мне нравится это решение, оно выглядит более чистым и имеет больше смысла. – RickCJ7

+0

Как вычесть ev.taken_sum из ev.forward_sum в новый столбец? Я попробовал sum (ev.forward_sum - ev.taken_sum) как «10/24 Balance» , но это дает мне группу по ошибке. Благодаря! – RickCJ7

+0

Как вычесть 'ev.taken_sum' из' ev.forward_sum'? Ну, со знаком минуса, конечно: 'ev.forward_sum - ev.taken_sum'. Ваша дополнительная «сумма» просто не имеет смысла. –

2

Вам нужен свернутый запрос, в котором подзапрос использует значение из «родительского» запроса.

SELECT e.PIN ... 
    (select SUM(value) .... WHERE EmployeeID = e.id) as taken 
               ^^^^^ 

Обратите внимание, что они могут быть очень неэффективными, так как внутренний запрос должен быть выполнен один раз для каждой строки родительского запроса. Во многих случаях вам может быть лучше переписать в качестве обычного JOIN запрос с соответствующей группировкой.

+0

Акцент на последнем абзаце Mac. Вероятность 99% это может быть написано более эффективно. – scsimon

+0

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

+0

Поскольку я не эксперт по SQL с использованием Joins, предложение Marc работало. Спасибо, Марк! – RickCJ7

Смежные вопросы