2017-01-04 2 views
0

я есть 3 таблицыMYSQL влево присоединиться и внутреннее соединение

Сотрудник => e_id (ПК), dep_id (Fk)

отдел => d_id (PK)

Перенаправление => Id (PK), date_of_absence (DATE), e_id_f (FK)

Я хочу получить количество отсутствующих сотрудников в определенном отделе на определенный период.

я создал таблицу под названием MyDates

CREATE TABLE MyDates (mydate date); 

и эту процедуру, чтобы заполнить MyDates таблицу с датами

CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE) 

НАЧАТЬ

WHILE dateStart <= dateEnd DO 
    INSERT INTO MyDates (mydate) VALUES (dateStart); 
    SET dateStart = date_add(dateStart, INTERVAL 1 DAY); 
    END WHILE; 
END; 

затем я назвал процедуру, чтобы заполнить MyDates с датой CALL filldates ('2017-01-01', '2017-03-31');

Тогда я сделал это отборное заявление:

select mydates.mydate, count(attendance.date_of_absence) 
from mydates left join attendance on 
mydates.mydate = attendance.date_of_absence 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" 
group by mydates.mydate 

Этот запрос получает то, что мне нужно, но и для всех ведомств, но и для определенного отдела количество строк неверен

select mydates.mydate, count(attendance.date_of_absence) 
from mydates 
left join attendance on mydates.mydate = attendance.date_of_absence 
inner join employee on attendance.e_id_f = employee.e_id 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" AND employee.dep_id = 4 
group by mydates.mydate; 

Это снимок экрана IMG

+0

можете ли вы добавить какие данные вам нужны и какой набор результатов вы получаете в форме образца. – meet

+0

уверен, пожалуйста, посмотрите на скриншот, добавленный выше. –

ответ

0

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

  1. inner join employee on attendance.e_id_f = employee.e_id - если нет соответствующих записей в течение дня, то attendance.e_id_f будет нулевым для тот день. Внутреннее соединение удалит эту запись из набора результатов. Решение: сделайте это соединение также левым.

  2. AND employee.dep_id = 4 - это будет вести только записи в наборе результатов, у которых есть запись сотрудника, связанная с ним, поэтому, если у вас есть день с 0 отсутствием, этот критерий устранит его из набора результатов. Решение: включите этот критерий в условие соединения.

  3. count(attendance.date_of_absence) - подсчеты из таблицы посещаемости, что не будет правильным после добавления второго левого соединения. Решение: вместо этого используйте count(employee.dep_id).

Измененный запрос:

select mydates.mydate, count(employee.dep_id) 
from mydates 
left join attendance on mydates.mydate = attendance.date_of_absence 
left join employee on attendance.e_id_f = employee.e_id AND employee.dep_id = 4 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" group by mydates.mydate 

Альтернативное решение заключается в использовании вложенных соединений, где вы специально инструктировать MySQL для выполнения attendance inner join employee присоединиться к первой.Вам все еще нужно, чтобы переместить условие employee.dep_id = 4 в условия соединения:

select mydates.mydate, count(attendance.date_of_absence) 
from mydates 
left join (attendance inner join employee) 
    on mydates.mydate = attendance.date_of_absence 
     and attendance.e_id_f = employee.e_id 
     and employee.dep_id = 4 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" 
group by mydates.mydate 

В последнем случае вложенная внутреннее соединение гарантирует, что только те записи посещаемости возвращаются, которые принадлежат dep_id = 4 и эти записи затем налево присоединились к вашим датам Таблица. В этом случае нет необходимости изменять поле, которое вы подсчитываете.

+0

Отлично, спасибо много Тень –

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