Lista
04 - Gabarito
--1. Obtenha o nome e salário dos empregados e caso o empregado seja coordenador de algum projeto, o código e orçamento do projeto que o empregado coordena.
SELECT E.nome, E.salario, P.pcodigo, P.orçamento FROM EMPREGADOS E
LEFT JOIN PROJETOS P ON E.ecodigo = P.coordenador; (60 rows)
--2. Obtenha o nome e local de trabalho dos empregados e caso o empregado seja gerente de algum departamento, o código do departamento que o empregado gerencia.
SELECT E.nome, D1.local, D2.dcodigo FROM EMPREGADOS E
INNER JOIN DEPARTAMENTOS D1 ON E.dcodigo = D1.dcodigo LEFT JOIN DEPARTAMENTOS D2 ON E.ecodigo = D2.gerente; (53 rows)
--3. Obtenha a média de salarios do departamento “D30” (dcodigo igual a 30).
SELECT AVG(E.salario) AS MEDIA_SALARIO FROM EMPREGADOS E
WHERE E.dcodigo = 30;
--4. Obtenha o maior salário da empresa.
SELECT MAX(E.salario) AS MAIOR_SALARIO FROM EMPREGADOS E;
--5. Obtenha o nome do coordenador do projeto de maior orçamento.
SELECT E.nome, P1.orçamento FROM PROJETOS P1
INNER JOIN EMPREGADOS E ON P1.coordenador = E.ecodigo WHERE P1.orçamento IN (
SELECT MAX(P2.orçamento) FROM PROJETOS P2
);
--6. Obtenha o departamento que tem o empregado de maior salário.
SELECT E1.dcodigo FROM EMPREGADOS E1 WHERE E1.salario IN (
SELECT MAX(E2.salario) FROM EMPREGADOS E2 );
--7. Obtenha a soma dos salários de todos os empregados que trabalham no departamento “D30” (dcodigo igual a 30).
SELECT SUM(E.salario) FROM EMPREGADOS E WHERE E.dcodigo = 30;
--8. Para cada departamento, obtenha o número de empregados que trabalham naquele departamento e a soma dos seus salários.
SELECT D.dcodigo, COUNT(E.ecodigo) AS Numero_Funcionarios, SUM(E.salario) FROM EMPREGADOS E
RIGHT JOIN DEPARTAMENTOS D ON E.dcodigo = D.dcodigo GROUP BY (D.dcodigo)
ORDER BY D.dcodigo;
-- ORDER BY Não necessário, só para organizar o resultado
--9. Para cada departamento, obtenha o número de empregados que trabalham naquele departamento e a soma dos seus salários. Exclua os departamentos com número de empregados menor do que 30.
SELECT D.dcodigo, COUNT(E.ecodigo) AS Numero_Funcionarios, SUM(E.salario) FROM EMPREGADOS E
RIGHT JOIN DEPARTAMENTOS D ON E.dcodigo = D.dcodigo GROUP BY (D.dcodigo)
--10. Obtenha o departamento, que tem a maior média de salários.
-- Solução 01
CREATE VIEW V1(dnumero, media) AS SELECT D.dcodigo, AVG(E.salario) FROM EMPREGADOS E
RIGHT JOIN DEPARTAMENTOS D ON E.dcodigo = D.dcodigo GROUP BY D.dcodigo;
SELECT V1.dnumero, V1.media
FROM V1 WHERE V1.media IN ( SELECT MAX(V1.media) FROM V1 );
-- Solução 02
SELECT V1.dnumero, V1.media FROM V1 WHERE V1.media >= ALL (
SELECT V1.media FROM V1
where V1.media IS NOT NULL );
-- Solução 03 - sem Visão
SELECT V.dnumero, V.media FROM (
SELECT D.dcodigo as dnumero, AVG(E.salario) as media FROM EMPREGADOS E
RIGHT JOIN DEPARTAMENTOS D ON E.dcodigo = D.dcodigo GROUP BY D.dcodigo
) V
WHERE V.media IN (
SELECT MAX(V2.media) FROM (
SELECT D.dcodigo, AVG(E.salario) as media FROM empregados E
RIGHT JOIN DEPARTAMENTOS D ON E.dcodigo = D.dcodigo GROUP BY D.dcodigo
) V2 )
--11. Obtenha o número de horas que o empregado “E21” (ecodigo igual a 21) trabalha no projeto “P1” (pcodigo igual a 1).
SELECT T.numHoras FROM TRABALHA T
WHERE T.ecodigo = 21 AND T.pcodigo = 1;
--12. Obtenha o número total de horas que o empregado “E21” (ecodigo igual a 21) trabalha (considerando todos os projetos que ele trabalha).
SELECT SUM(T.numHoras) FROM TRABALHA T
--13. Para cada projeto, obtenha o número de horas que o empregado “E21” (ecodigo igual a 21) trabalha.
-- No caso em que o empregado “E21” não trabalhe no projeto o valor deve ser Null. SELECT P.pcodigo, T.numHoras
FROM (
SELECT *
FROM TRABALHA WHERE ecodigo = 21 ) T
RIGHT JOIN PROJETOS P ON T.pcodigo = P.pcodigo; (16 rows)
-- 14. Obtenha o número total de horas que os empregados trabalham no projeto “P21” (pcodigo igual a 21).
SELECT SUM(T.numHoras) FROM TRABALHA T
-- 15. Para cada empregado, obtenha o nome do empregado e o total de horas que ele trabalha em cada projeto. No caso em que o empregado não trabalhe em algum projeto o valor deve ser Null.
SELECT E.nome, T.pcodigo, T.numHoras FROM EMPREGADOS E
LEFT JOIN TRABALHA T ON E.ecodigo = T.ecodigo LEFT JOIN PROJETOS P ON P.pcodigo = T.pcodigo ORDER BY e.nome;
--OBS: ORDER BY não é necessario, mas melhora a visualização do resultado (60 rows)
--16. Para cada departamento, obtenha o número de empregados desse departamento que trabalham em cada projetos.
SELECT D.dcodigo, T.pcodigo, COUNT( E.ecodigo) FROM DEPARTAMENTOS D
LEFT JOIN EMPREGADOS E ON D.dcodigo = E.dcodigo LEFT JOIN TRABALHA T ON E.ecodigo = T.ecodigo GROUP BY D.dcodigo, T.pcodigo
(22 rows)
-- Bonus: Para mostrar realmente todo par (departamento, projeto) teriamos que fazer assim:
SELECT V1.dcodigo, V1.pcodigo, COUNT(V2.ecodigo) FROM (
SELECT D.DCODIGO, P.PCODIGO
FROM DEPARTAMENTOS D, PROJETOS P ORDER BY D.DCODIGO, P.PCODIGO ) V1 LEFT JOIN (
SELECT E.ecodigo, E.dcodigo, T.pcodigo FROM EMPREGADOS E
INNER JOIN TRABALHA T ON E.ecodigo = T.ecodigo
) V2 ON V1.dcodigo = V2.dcodigo and V1.pcodigo = V2.pcodigo group by V1.dcodigo, V1.pcodigo
ORDER BY v1.dcodigo, v1.pcodigo (96 rows)
--17. Nome dos empregados que coordenam mais de 3 projetos.
-- Solução 01
CREATE VIEW V17(ecodigo, nome, NumProj) AS SELECT E.ecodigo, E.nome, COUNT(P.pcodigo) FROM EMPREGADOS E, PROJETOS P
WHERE E.ecodigo = P.coordenador GROUP BY E.ecodigo;
SELECT V17.nome FROM V17
WHERE NumProj > 3; -- Solução 02 - Sem View
SELECT E.nome
FROM EMPREGADOS E, PROJETOS P WHERE E.ecodigo = P.coordenador GROUP BY E.ecodigo
HAVING COUNT(*) > 3 -- Solução 03 - Sem View
SELECT E.nome
FROM EMPREGADOS E WHERE E.ecodigo IN (
SELECT P.coordenador FROM PROJETOS P GROUP BY P.coordenador HAVING COUNT(P.pcodigo) > 3 );
Solução 04 - Sem view SELECT E.nome FROM empregados E WHERE (
select count(*) from projetos
--18. Nome dos departamentos que têm mais empregados que o departamento D 20.
-- (Foi alterado o valor do codigo de departamento para o 20 (que não tem empregados) para ter resultado)
SELECT D.dcodigo, D.nome FROM EMPREGADOS E
INNER JOIN DEPARTAMENTOS D ON E.dcodigo = D.dcodigo GROUP BY D.dcodigo
HAVING COUNT( E.ecodigo) > (
SELECT COUNT(DISTINCT E1.ecodigo) FROM EMPREGADOS E1
WHERE E1.dcodigo = 20 );
--19. Obtenha os nomes dos empregados que ganham mais do que o gerente do seu departamento.
SELECT E1.nome
FROM EMPREGADOS E1
INNER JOIN DEPARTAMENTOS D ON E1.dcodigo = D.dcodigo INNER JOIN EMPREGADOS E2 ON D.gerente = E2.ecodigo WHERE E1.salario > E2.salario
--20. Liste os códigos dos projetos que têm um empregado chamado “JOAO SILVA” que trabalha no projeto ou gerencia o departamento que controla o projeto. (Funciona mudando o nome do funcionário para “Narciso”, por exemplo)
-- Solução 01
SELECT DISTINCT (T.pcodigo) FROM TRABALHA T
INNER JOIN PROJETOS P ON T.pcodigo = P.pcodigo WHERE T.ecodigo = (
SELECT E.ecodigo FROM EMPREGADOS E WHERE E.nome = 'Narciso' )
OR P.coordenador = (
SELECT E1.ecodigo FROM EMPREGADOS E1
WHERE E1.nome = 'Narciso' ) ; -- Solução 02
SELECT DISTINCT(T.pcodigo) FROM TRABALHA T
INNER JOIN PROJETOS P ON T.pcodigo = P.pcodigo WHERE T.ecodigo IN (
SELECT E.ecodigo FROM EMPREGADOS E WHERE E.nome = 'Narciso' ) OR P.coordenador IN (
SELECT E1.ecodigo FROM EMPREGADOS E1 WHERE E1.nome = 'Narciso' )
--21. Obtenha os nomes dos empregados que não trabalham em nenhum projeto.
-- Solução 01
SELECT e.nome FROM empregados e WHERE e.ecodigo NOT IN (
SELECT distinct ecodigo FROM trabalha
) -- Solução 02
SELECT e.nome FROM empregados E WHERE NOT EXISTS (
SELECT *
FROM trabalha T
WHERE T.ecodigo = E.ecodigo )
--22. Obtenha os nomes dos empregados que trabalham em pelo menos um projeto.
-- Solução 01
SELECT e.nome FROM empregados e WHERE e.ecodigo IN (
SELECT distinct ecodigo FROM trabalha
) -- Solução 02
SELECT e.nome FROM empregados E WHERE EXISTS (
SELECT * FROM trabalha T
WHERE T.ecodigo = E.ecodigo )
--23. Liste os nomes dos empregados no departamento 'D30' que tem o maior salário
--OBS: Mudando para o departamento D30 para ter resultado -- Solução 01
SELECT E.nome
FROM EMPREGADOS E WHERE E.dcodigo = 30
AND E.salario IN (
SELECT MAX(E.salario) FROM EMPREGADOS E WHERE E.dcodigo = 30 );
-- Solução 02
SELECT e.nome FROM empregados E WHERE E.dcodigo = 30
AND e.salario >=ALL (
select max(empregados.salario)
From empregados where empregados.dcodigo = 30 )
--24. Para cada empregado obtenha o número de projetos que ele trabalha e o total de horas que trabalha nestes projetos.
SELECT T.ecodigo, COUNT(*), SUM(T.numHoras) FROM TRABALHA T
GROUP BY T.ecodigo (17 rows)
--25. Para cada empregado que trabalha em mais de um projeto obtenha nome dos empregados e número de projetos que trabalha. (MODIFICADA DA LISTA)
SELECT e.nome, count(*) FROM trabalha t
INNER JOIN empregados e ON e.ecodigo = t.ecodigo GROUP BY t.ecodigo , e.nome
--26. Para cada projeto que tem mais de 5 empregados alocados, obtenha o código do projeto, a média de horas que os empregados trabalham no projeto.
--OBS: resultado modificando para mais de 3 empregados SELECT T.pcodigo , COUNT(*), AVG(T.numHoras) FROM TRABALHA T
GROUP BY T.pcodigo HAVING count(*) > 3
--27. Obtenha os projetos que tem mais empregados do que a média dos projetos e total de horas alocadas maior do que a média dos projetos
CREATE VIEW V27 (pcodigo, quantidade_emp, horas_alocadas) AS SELECT T.pcodigo, COUNT(*) AS quantidade_emp, SUM(T.numHoras) FROM TRABALHA T GROUP BY T.pcodigo ;
SELECT * FROM V27 WHERE V27.quantidade_emp > ( SELECT AVG(V27.quantidade_emp) FROM V27 ) AND V27.horas_alocadas > ( SELECT AVG(V27.horas_alocadas) FROM V27 );
--28. Obtenha o nome e salário dos empregados que ganham um salário superior ao salário médio do respectivo departamento
SELECT E.nome, E.salario FROM EMPREGADOS E WHERE E.salario > (
SELECT AVG(E1.salario) FROM EMPREGADOS E1 WHERE E1.dcodigo = E.dcodigo );
--29. Obtenha o nome e salário dos empregados cujo salario médio do seu departamento é superior a media de salários do departamento D30.
-- OBS: Mudando para departamento 1 para ter resultado -- Solução 01
SELECT E.nome, E.salario FROM EMPREGADOS E WHERE E.dcodigo IN (
SELECT E1.dcodigo FROM EMPREGADOS E1 GROUP BY E1.dcodigo HAVING AVG(E1.salario) > (
SELECT AVG(E2.salario) FROM EMPREGADOS E2 WHERE E2.dcodigo = 1 ) )
-- Solução 02: Solução com visão
CREATE VIEW V29 (dnumero, med_sal_dep) AS SELECT E.dcodigo, AVG(E.salario)
FROM EMPREGADOS E GROUP BY E.dcodigo; SELECT E.nome, E.salario
FROM EMPREGADOS E, V29 V1 WHERE E.dcodigo = V1.dnumero
AND V1.med_sal_dep > ( SELECT med_sal_dep FROM V29 V2 WHERE V2.dnumero =1 ); (41 rows)