Pergunta

Acabei de saber (ontem) para uso "existe" em vez de "in".

 BAD
 select * from table where nameid in ( 
          select nameid from othertable where otherdesc =  'SomeDesc' )      
 GOOD
 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      

E eu tenho algumas perguntas sobre isso:

1) A explicação que eu entendi foi: "A razão para isso é melhor é porque somente os valores correspondentes serão devolvidos em vez de construir uma enorme lista de possíveis resultados" . Isso significa que, enquanto a primeira subconsulta pode retornar 900 resultados da segunda irá retornar apenas 1 (sim ou não)?

2) No passado eu tive a complainin RDBMS: "apenas os primeiros 1000 linhas pode ser recuperada", esta segunda abordagem resolveria esse problema

3) Qual é o escopo do alias na segunda subconsulta? ... não o alias só vive no parêntese?

Por exemplo

 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      
 AND 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeOtherDesc' )      

Isto é, se eu usar o mesmo alias (o para a tabela tbl_outra) No segundo "existe" será que vai apresentar qualquer problema com a primeira existe? ou são totalmente independentes?

Isto é algo somente Oracle relacionado ou ele é válido para a maioria dos RDBMS?

Muito obrigado

Foi útil?

Solução

Ele é específico para cada DBMS e depende do otimizador de consulta. Alguns otimizadores detectar cláusula IN e traduzi-lo.

Em todos os DBMSes I testados, alias é válido somente dentro do ()

BTW, você pode reescrever a consulta como:

select t.* 
from table t 
join othertable o on t.nameid = o.nameid 
    and o.otherdesc in ('SomeDesc','SomeOtherDesc');

E, para responder às suas perguntas:

  1. Sim
  2. Sim
  3. Sim

Outras dicas

Você está pisando em território complicado, conhecido como 'sub-consultas correlatas'. Uma vez que ainda não temos informação sobre suas mesas e as estruturas principais, algumas das respostas só pode ser 'talvez' detalhado.

Na sua consulta IN inicial, a notação seria válido ou não tbl_outra contém uma NameID coluna (e, de fato, se OtherDesc existe como uma coluna na tabela ou tbl_outra - que não é claro em qualquer um dos seus exemplos, mas presumivelmente é uma coluna de tbl_outra). Este comportamento é o que faz uma sub-consulta correlacionada em uma sub-consulta correlacionada. É também uma fonte de rotina de angústia para as pessoas quando eles correr para ele - invariavelmente por acidente. Uma vez que os mandatos padrão SQL o comportamento de interpretar um nome na sub-consulta como referindo-se a uma coluna na consulta externa se não houver nenhuma coluna com o nome pertinente nos quadros mencionados no sub-consulta, mas há uma coluna com o nome relevante nas tabelas mencionadas na consulta externa (principal), nenhum produto que quer reivindicação de conformidade para (este bocado de) o padrão SQL vai fazer nada diferente.

A resposta à sua Q1 é "depende", mas dadas hipóteses plausíveis (NameID existe como uma coluna em ambas as tabelas; OtherDesc só existe em tbl_outra), os resultados devem ser os mesmos em termos do conjunto de dados retornados, mas pode não ser equivalente em termos de desempenho.

A resposta à sua Q2 é que, no passado, você estava usando um inferior se DBMS não defeituosos. Se suportado existe, então o DBMS pode ainda queixar-se a cardinalidade do resultado.

A resposta à sua Q3 aplicada à primeira consulta EXISTS é "t está disponível como um alias em toda a declaração, mas o só está disponível como um alias dentro dos parênteses". Como aplicado ao seu exemplo caixa de segunda - com e ligar dois subseleções (o segundo dos quais está faltando o parêntese de abertura quando eu estou olhando para ele), então "t está disponível como um alias em toda a declaração e refere-se à mesma mesa, mas há dois apelidos diferentes, tanto rotulados 'o', um para cada sub-consulta". Note que a consulta pode devolver sem dados se OtherDesc é único para um dado valor NameID em tbl_outra; caso contrário, ele requer duas linhas em tbl_outra com o mesmo NameID e os dois valores OtherDesc para cada linha na tabela com esse valor NameID.

  1. específico do Oracle: Quando você escrever uma consulta usando a cláusula IN, você está dizendo que o otimizador baseado em regras que deseja a consulta interna para conduzir a consulta externa. Quando você escreve existe em uma cláusula WHERE, você está dizendo que o otimizador que deseja que a consulta externa a ser executado primeiro, usando cada valor para buscar um valor da consulta interna. Consulte "Diferença entre IN e existe em subqueries ".
  2. Provavelmente.
  3. Alias ??declarada dentro vidas subconsulta dentro subconsulta. By the way, eu não acho que o seu exemplo com 2 subqueries AND é SQL válido. Você quis dizer UNION em vez de E?

Pessoalmente eu gostaria de usar uma associação, em vez de uma subconsulta para isso.

SELECT t.*
FROM yourTable t
    INNER JOIN otherTable ot
        ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc')

É difícil generalizar que existe é sempre melhor do que IN. Logicamente, se for esse o caso, então comunidade SQL teria substituído IN com EXISTE ... Também, por favor note que no e existe não são os mesmos, os resultados podem ser diferentes quando você usa os dois ...

Com IN, geralmente é uma varredura completa da tabela da tabela interna uma vez sem remover nulos (por isso, se você tem nulos em sua tabela interna, IN não irá remover NULLS por padrão) ... Enquanto EXISTE remove NULL e em caso de subconsulta correlacionada, corre consulta interna para cada linha da consulta externa.

Assumindo que não há NULLS e sua uma consulta simples (sem correlação), EXIST pode executar melhor se a linha você está encontrando não é a última linha. Se ele passa a ser a última linha, EXISTE pode precisar digitalizar até que termine como em .. desempenho tão semelhantes ...

Mas IN e EXISTS não são intercambiáveis ??...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top