#sql
#sql
Вопрос:
У меня есть 4 таблицы:
employee
:employee_id
(и несколько несвязанных столбцов)calls
:employee_id
,date
,number_of_calls
(на указанную дату сотрудником)employee_skills
:employee_id
,skills_id
skills
:skills_id
,primary_skill
,secondary_skill
В качестве примечания к сайту: в employee_skills
комбинациях primary_skill
и secondary_skill
может встречаться несколько раз с разными skill_id
. Может быть две записи, такие как 234 | Python | Java
и 235 | Python | Java
.
Я хотел бы иметь SELECTS
оператор -, который возвращает: employee_id
, number_of_total_calls
(этого сотрудника), number_of_unique_secondary_skills
(этого сотрудника)
Проблема, с которой я сталкиваюсь, связана с number_of_total_calls_of_employee
. Когда я только объединяю таблицы employee
и calls
, я получаю правильное количество (сумму) общих вызовов этого сотрудника. Однако, когда я также присоединяюсь к таблицам employee_skills и skills, я получаю кратное правильное число (например, в 6 раз больше правильного числа для employee_id
123). Я думаю, что это так, поскольку при этом employee_id
происходит несколько раз в новой таблице, а не только один раз ( employee_id
123
происходит 6 раз в новой таблице), поскольку employee_id
в таблице несколько раз employee_skills
(например employee_id
123
, происходит 6 раз в employee_skills
).
Оператор SELECT
-, который я использую, выглядит следующим образом:
SELECT e.employee_id, SUM(c.number_of_calls), COUNT(DISTINCT s.secondary_skill)
FROM employees e
INNER JOIN calls c
ON e.employee_id = c.employee_id
INNER JOIN employee_skills es
ON e.employee_id = es.employee_id
INNER JOIN skills s
ON es.skills_id = s.skills_id
GROUP BY e.employee_id;
Ответ №1:
Во-первых, вам не нужна таблица employees, потому employee_id
что она есть в обеих других таблицах. Затем я бы рекомендовал агрегировать данные по обоим измерениям перед объединением:
SELECT es.employee_id, c.number_of_calls, es.num_secondary_skills
FROM (SELECT c.employee_id, SUM(c.number_of_calls) as number_of_calls
FROM calls c
GROUP BY c.employe_id
) c JOIN
(SELECT es.employee_id, COUNT(DISTINCT s.secondary_skill) as num_secondary_skills
FROM employee_skills es JOIN
skills s
ON es.skills_id = s.skills_id
GROUP BY es.employee_id
) es
ON es.employee_id = c.employee_id;
Вышесказанное возвращает только тех сотрудников, у которых есть как призвания, так и навыки. Если некоторым сотрудникам не хватает того или иного, то они отфильтровываются.
Если вам нужны все сотрудники, тогда employees
таблица удобна — с внешними соединениями:
SELECT e.employee_id, c.number_of_calls, es.num_secondary_skills
FROM employees e LEFT JOIN
(SELECT c.employee_id, SUM(c.number_of_calls) as number_of_calls
FROM calls c
GROUP BY c.employe_id
) c
ON c.employee_id = e.employee_id LEFT JOIN
(SELECT es.employee_id, COUNT(DISTINCT s.secondary_skill) as num_secondary_skills
FROM employee_skills es JOIN
skills s
ON es.skills_id = s.skills_id
GROUP BY es.employee_id
) es
ON es.employee_id = e.employee_id;
Ответ №2:
Просто возьмите сумму вызовов отдельно как внутренний запрос.
SELECT e.employee_id,
( SELECT SUM(c.number_of_calls) FROM calls c WHERE c.employee_id = e.employee_id ) as sum_of_calls,
COUNT(DISTINCT s.secondary_skill)
FROM employees e
INNER JOIN calls c
ON e.employee_id = c.employee_id
INNER JOIN employee_skills es
ON e.employee_id = es.employee_id
INNER JOIN skills s
ON es.skills_id = s.skills_id
GROUP BY e.employee_id;