SubQuery

Esse é um recurso avançado e extremamente útil do comando SELECT. Na prática, será colocado um SELECT dentro de outro. Isso quer dizer que serão colocados vários SELECTs internos. Subqueries faz parte do padrão SQL-86, logo todos os bancos de dados relacionados que utilizam SQL devem permitir essa utilização.

Há três tipos de subquery:

  • De uma linha: O retorno do SELECT interno será uma única linha.
  • Subquery de múltiplas linhas: O retorno do SELECT interno será mais de uma linha.
  • Subquery de múltiplas colunas: O retorno do SELECT interno conterá mais de uma linha e coluna.

Para realizar subqueries tenha em mente:

  • Coloque as subqueries entre parêntese.
  • Coloque a subquery à direita do operador.
  • Não coloque a cláusula ORDER BY em uma subquery
  • Utilize operadores de linha apenas em buscas que retornem uma única linha.
  • utilize operadores de grupo apenas em buscas que potencialmente retornem mais de uma linha.

Subquery de uma linha

Neste caso, o resultado do SELECT mais interno servirá de base para o primeiro SELECT. Ao utilizarmos essa forma de busca, poderemos até melhorar o desempenho do banco de dados. Uma alternativa para essa forma de realizar a busca seria fazer uma União regular de tabelas. Dependendo do que queremos buscar nas tabelas, esse comando é mais indicado em virtude da velocidade. Note que fazendo a união regular de tabelas, estamos combinando todas as linhas de ambas as tabelas. Primeiro é feita a busca em uma tabela e, com base no resultado, pesquisada a outra tabela. Veja um exemplo:

SELECT NOME_CD, PRECO_VENDA FROM CD

WHERE PRECO_VENDA > (SELECT AVG(PRECO_VENDA) FROM CD);

Aqui é utilizada uma subquery para verificar a média do preço e, com base nesse resultado, é extraído o resultado da busca do primeiro SELECT (nome e preço). Só aparecerá no resultado os registros que o preço seja maior que a média.

SELECT CODIGO_GRAVADORA, NOME_CD, PRECO_VENDA FROM CD a

WHERE PRECO_VENDA > (SELECT AVG(PRECO_VENDA) FROM CD

WHERE CODIGO_GRAVADORA = a.CODIGO_GRAVADORA);

O segundo SELECT retorna a média de preço de venda dos CDs da gravadora do primeiro SELECT e somente os que tiverem preço de venda maiores que essa média é que aparecerão na listagem.

Subquery de múltiplas colunas

A primeira técnica consiste em colocar as colunas unidas na cláusula WHERE do SELECT externo e realizar a busca no SELECT interno dessas colunas unidas da mesma forma. Essa técnica tende a ser muito lenta, mas pode ser feita em qualquer banco de dados.

A utilização é muito parecida com as visões. Uma subquery na cláusula FROM define a fonte de dados para esse SELECT em particular. Imagine que desejemos extrair o nome do CD, o seu preço de venda e o preço médio da gravadora, e o preço médio da gravadora é extraído por uma subquery na própria cláusula FROM.

select a.nome_cd, a.preco_venda, b.avg from cd a,

(select codigo_gravadora, avg(preco_venda) from cd

group by codigo_gravadora) b

where a.codigo_gravadora = b.codigo_gravadora and

a.preco_venda > b.avg

Subquery de múltiplas linhas

Neste caso, o SELECT interno retorna mais de uma linha. Não se pode utilizar operadores simples como igualdade, diferença, maior ou menor. Deve-se utilizar um operador de grupo para realizar a comparação. Esses operadores são ANY, ALL e IN.

IN

Imagine que gostaríamos de saber quais CDs têm o preço igual ao menor preço de cada gravadora. Inicialmente devemos saber qual o menor preço de cada gravadora. Isso pode ser feito com o comando:

Select min(preco_venda) from CD Group by Codigo_gravadora

Select codigo_cd, nome_cd, preco_venda from cd Where preco_venda in (15,9,10.5)

Para saber quais são os CDs com esses preço, poderíamos escrever o seguinte comando:

Para fazer isso tudo em um único comando, escrevemos o comando da seguinte forma:

select codigo_cd, nome_cd, preco_venda from cd

where preco_venda in (select min(preco_venda) from cd

group by codigo_gravadora)

Uma outra situação em que poderíamos utilizar esse operador é quando queremos saber em qual CD e faixa há músicas que tenham AMOR no nome. Para isso, temos que utilizar as linhas da tabela MUSICA e compará-las com AMOR. Não esquecer de colocar a função UPPER do nome do campo pois, para efetuar a comparação com sucesso, devemos ter certeza de que o conteúdo da coluna esteja em letras maiúsculas, uma vez que escrevemos AMOR em letras maiúsculas. Veja a seguir:

Select codigo_musica from musica

Where upper(nome_musica) like '%AMOR%';

Sabendo quais são os código da música, podemos realizar uma busca na tabela FAIXA que nos informe em quais CDs e faixas estão essas músicas. Assim:

Select codigo_cd, numero_faixa from faixa

Where codigo_musica in (25,2)

Da mesma forma, podemos simplificar o comando realizando tudo isso em uma única operação:

Select codigo_cd, numero_faixa from faixa

Where codigo_musica in (select codigo_musica from musica

where upper(nome_musica) like '%AMOR%')

ANY

Esse operador permite comparar operadores simples (=, >, <, !=) com um grupo de linhas. Será feita a comparação com cada valor retornado do SELECT interno.

Imagine que desejamos saber quais CDs têm preço inferior a qualquer outro da gravadora com código 2, mas que não sejam da gravadora 2. E pesquisando na tabela CD para comparar os preços inferiores a esses

select codigo_cd, nome_cd, preco_venda from cd

where preco_venda < any(select preco_venda from cd

where codigo_gravadora = 2) and codigo_gravadora !=2

Podemos ainda utilizar o mesmo operador any com os outros operadores simples, veja o exemplo a seguir:

select codigo_cd, nome_cd, preco_venda from cd

where preco_venda = any(select preco_venda from cd

where codigo_gravadora = 2)

Observe neste exemplo não existe mais a condição do código da gravadora ser diferente de 2, caso contrário, não existiriam linhas de retorno.

ALL

Este operador é utilizado em combinação com operadores simples (>,<) para que os valores retornados de todas as linhas do SELECT interno sejam comparados com o SELECT externo.

Imagine que queiramos saber quais CDs têm o preço de venda menor que a média de preço de venda de todas as gravadoras. Inicialmente é necessário saber a média de preços por gravadora:

 

Select avg(preco_venda) from cd Group by codigo_gravadora

Depois de verificarmos quais são os CDs com preço inferior a todos anteriores. O comando seria o seguinte:

 

Select codigo_cd, nome_cd, preco_venda from cd

Where preco_venda < all (array[15,11,11.75])

 

Em um único comando teríamos:

 

select codigo_cd, nome_cd, preco_venda from cd

where preco_venda < all(select avg(preco_venda) from cd

group by codigo_gravadora)

SubQuery

By walternascimento