Sub Query dando erro

5 respostas
D

Pessoal tenho essa consulta com uma subquery

SELECT A.CPF, A.NOME, SUM(c.valor) AS TOTAL_PAGO FROM CLIENTES A JOIN ALUGUEL B ON A.CPF = B.CPF_CLIENTE JOIN PAGAMENTOS C ON C.CPF_CLIENTE = B.CPF_CLIENTE and C.ID_MIDIA = B.ID_MIDIA where a.SEXO = 'F' and (select al.cpf_cliente, count(al.cpf_cliente) as quant from aluguel al group by al.cpf_cliente having quant > 5) group by a.cpf, a.nome

A sub query sozinha funciona, agora quando colocada onde eu preciso da esse erro -> operand should contain 1 column(s)

Alguém pode me ajudar??

5 Respostas

R

Sua subquery não tá comparando nada, ela é = > < a nada.

Uma dica, leia

http://www.criarweb.com/artigos/subconsultas-em-sql.html

D

Renatobh:
Sua subquery não tá comparando nada, ela é = > < a nada.

Uma dica, leia

http://www.criarweb.com/artigos/subconsultas-em-sql.html

Renato eu coloquei o exists e funcionou, mas teria como vc me explicar pq nao to conseguindo entender bem =/

SELECT A.CPF, A.NOME, SUM(c.valor) AS TOTAL_PAGO FROM CLIENTES A JOIN ALUGUEL B ON A.CPF = B.CPF_CLIENTE JOIN PAGAMENTOS C ON C.CPF_CLIENTE = B.CPF_CLIENTE and C.ID_MIDIA = B.ID_MIDIA where a.SEXO = 'M' and exists(select al.cpf_cliente, count(al.cpf_cliente) as quant from aluguel al group by al.cpf_cliente having quant >= 10) group by a.cpf, a.nome

O exists vai me retornar true se a consulta retornar alguma linha, nesse caso esse subSelect eu preciso dos clientes que tem no minimo 10 alugueis, mas como essa consulta sabe que é o mesmo CPF q eu estou tentando projetar la no primeiro select?

E

como a subconsulta está no “where” da consulta, você pode usar os campos da consulta como filtros na subconsulta, ficaria assim então:

SELECT A.CPF, A.NOME, SUM(c.valor) AS TOTAL_PAGO FROM CLIENTES A JOIN ALUGUEL B ON A.CPF = B.CPF_CLIENTE JOIN PAGAMENTOS C ON C.CPF_CLIENTE = B.CPF_CLIENTE and C.ID_MIDIA = B.ID_MIDIA where a.SEXO = 'M' and exists(select al.cpf_cliente, count(al.cpf_cliente) as quant from aluguel al where al.cpf_cliente = a.cpf group by al.cpf_cliente having quant >= 10) group by a.cpf, a.nome

Mas como existe group by na subconsulta, eu recomendaria você usar o “in” ao invés do exists, assim possivelmente tem um desempenho melhor:

SELECT A.CPF, A.NOME, SUM(c.valor) AS TOTAL_PAGO FROM CLIENTES A JOIN ALUGUEL B ON A.CPF = B.CPF_CLIENTE JOIN PAGAMENTOS C ON C.CPF_CLIENTE = B.CPF_CLIENTE and C.ID_MIDIA = B.ID_MIDIA where a.SEXO = 'M' and a.cpf in (select al.cpf_cliente from aluguel al group by al.cpf_cliente having count(al.cpf_cliente) >= 10) group by a.cpf, a.nome

Ou, a opção que eu prefiro (tanto por desempenho quanto para a manutenção do código) usar o inner join com a subconsulta:

SELECT A.CPF, A.NOME, SUM(c.valor) AS TOTAL_PAGO FROM CLIENTES A JOIN ALUGUEL B ON A.CPF = B.CPF_CLIENTE JOIN PAGAMENTOS C ON C.CPF_CLIENTE = B.CPF_CLIENTE and C.ID_MIDIA = B.ID_MIDIA JOIN (select al.cpf_cliente from aluguel al group by al.cpf_cliente having count(al.cpf_cliente) >= 10) AL ON a.cpf = AL.cpf_cliente where a.SEXO = 'M' group by a.cpf, a.nome

E

Explicação:

No primeiro caso, quando vc utiliza o “exists”, a subconsulta será executada para cada uma das linhas “resultado” dos joins anteriores, normalmente apresenta melhor desempenho em consultas que se precisa verificar se existe qualquer linha, sem se importar com a quantidade de linhas que serão retornadas na subconsulta, pois ela “para” e retorna ‘true’ quando encontra o primeiro resultado.

Já no segundo caso, quando você utiliza o IN, a subconsulta será executada 1 vez (por não existir parâmetros das consultas externas dentro da subconsulta, embora alguns poucos SGBDs executem uma vez para cada linha resultado dos joins, normalmente em versões antigas), e essa vez que será executada, será depois dos resultados dos joins (pode até ser em paralelo, mas a verificação do IN será depois dos joins). Esse caso costuma ter desempenho melhor quando você precisa aplicar filtros a outras subconsultas (por exemplo, um agrupamento necessariamente antes do filtro no IN, ou um conjunto de joins que precisam ser feitos exclusivamente antes do filtro no IN)

O terceiro caso, o banco vai fazer a subconsulta e o join “em paralelo” aos outros joins, escolhendo a melhor opção de acordo com as estatísticas interna dele. Normalmente ele faz os joins das tabelas com menores quantidades de registros, mas não é regra, as estatísticas dele são mais complexas que isso. Dessa forma, ele só vai cruzar os resultados das consultas que não pareça ser o caminho mais oneroso para ele. (por exemplo, se eu tenho a tabela A com 1000000 de registros, a B com 1000000, etc… mas a AL com 1000 registros, ele provavelmente vai executar primeiro o cruzamento com essas, antes de cruzar as outras, pois provavelmente vai reduzir a quantidade de linhas comparadas com as outras tabelas)

D

evefuji, cara MUITO BOA sua explicação, muito obrigado mesmo cara!!!

Criado 25 de maio de 2012
Ultima resposta 26 de mai. de 2012
Respostas 5
Participantes 3