Questão de SQL no POSCOMP 2011

E ai pessoas!

Estes dias, meu amigo Vitor Augusto (@VitorBitner) que realizou a pouco tempo o teste do POSCOMP, me encaminhou uma das questões que caíram no teste relacionadas á linguagem SQL, bem divertida por sinal.

Abaixo a questão:

51. Considere a relação a seguir, definida na linguagem SQL padrão.

CREATE TABLE EMPREGADO (
CODIGO NUMBER(4) PRIMARY KEY,
NOME VARCHAR2(10),
SALARIO NUMBER(7,2)
)

Considere também as consultas (C1, C2, C3 e C4) a seguir, expressas na linguagem SQL.

C1:

select NOME from EMPREGADO
where CODIGO in (
(select CODIGO from EMPREGADO)
minus
(select E1.CODIGO from EMPREGADO E1, EMPREGADO E2
where E1.SALARIO < E2.SALARIO)
)

Obs: o operador minus realiza a operação de subtração entre relações.

C2:

select NOME from EMPREGADO
where SALARIO = (select max(SALARIO) from EMPREGADO)

C3:

select NOME from EMPREGADO
where SALARIO >= all (select SALARIO from EMPREGADO)

C4:

select NOME from EMPREGADO
where CODIGO in (
select E1.CODIGO
from EMPREGADO E1, EMPREGADO E2
where E1.SALARIO > E2.SALARIO
)

Com relação às consultas, assinale a alternativa correta.

a) Apenas as consultas C2 e C3 são equivalentes.
b) Todas as consultas são equivalentes.
c) Apenas as consultas C1 e C3 são equivalentes.
d) Apenas as consultas C1 e C4 são equivalentes.
e) Apenas as consultas C1, C2 e C3 são equivalentes.

Visto que não se trata de T-SQL, e não possuímos dados para testes, vamos adequar o código simular o cenário no SQL Server:

CREATE TABLE EMPREGADO (
	CODIGO INT,
	NOME VARCHAR(10),
	SALARIO DECIMAL(7,2),
	CONSTRAINT PK$EMPREGADO PRIMARY KEY (CODIGO)
)
GO

INSERT INTO EMPREGADO
VALUES
(1, 'José', 100.00),
(2, 'Agnaldo', 120.00),
(3, 'Mariana', 120.00),
(4, 'Luiz', 150.00),
(5, 'Flávia', 150.00),
(6, 'Otavio', 150.00),
(7, 'Lucia', 150.00)
GO

--C1

SELECT NOME FROM EMPREGADO WHERE CODIGO in (
	(SELECT CODIGO FROM EMPREGADO)
	EXCEPT
	(SELECT E1.CODIGO FROM EMPREGADO E1, EMPREGADO E2 WHERE E1.SALARIO < E2.SALARIO)
)

--C2 | Resultado igual a C1

SELECT NOME FROM EMPREGADO WHERE SALARIO = (
	SELECT MAX(SALARIO) FROM EMPREGADO
)

--C3 | Resultado igual a C1, C2

SELECT NOME FROM EMPREGADO WHERE SALARIO >= ALL (
	SELECT SALARIO FROM EMPREGADO
)

--C4 | Resultado diferente

SELECT NOME FROM EMPREGADO
WHERE CODIGO IN (
	SELECT E1.CODIGO
	FROM EMPREGADO E1, EMPREGADO E2
	WHERE E1.SALARIO > E2.SALARIO
)

Agora que sabemos quais as respostas corretas (C1, C2, C3), vamos pensar um pouco sobre estas consultas na vida real:

A primeira consulta é muito complexa para obter um resultado simples, além de ser difícil ser otimizada (sim, este JOIN de uma tabela com ela mesma e o EXCEPT assustam).

A terceira consulta não é complexa, mas pode assustar pessoas que não conhecem SQL (ALL e subquery), por outro lado, também não oferece muitas alternativas para ser otimizada.

A segunda é simples e exige pouco esforço para ser otimizada (índice sobre a coluna salário e um include da coluna nome já resolve), logo poderíamos dizer que é a alternativa mais adequada para obter este tipo de resultado.

Fiquem a vontade de comentar ou enviar outras questões!

Referências:

Prova do POSCOMP 2011:
http://www.cops.uel.br/concursos/112_poscomp_2011/11201.PDF

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s