Domanda

Ho appena imparato (ieri) a usare " esiste " invece di " 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 ho alcune domande al riguardo:

1) La spiegazione che ho capito è stata: "Il motivo per cui questo è meglio è perché verranno restituiti solo i valori corrispondenti invece di creare un enorme elenco di possibili risultati" . Ciò significa che mentre la prima sottoquery potrebbe restituire 900 risultati, la seconda restituirà solo 1 (sì o no)?

2) In passato ho avuto il reclamo RDBMS: "solo le prime 1000 righe potevano essere recuperate", questo secondo approccio avrebbe risolto quel problema?

3) Qual è lo scopo dell'alias nella seconda sottoquery? ... l'alias vive solo tra parentesi?

ad esempio

 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' )      

Cioè, se uso lo stesso alias (o per la tabella modificabile) Nel secondo "esiste". presenterà qualche problema con il primo esiste? o sono totalmente indipendenti?

È qualcosa che Oracle è solo correlato o è valido per la maggior parte dei RDBMS?

Grazie mille

È stato utile?

Soluzione

È specifico per ciascun DBMS e dipende da Query Optimizer. Alcuni ottimizzatori rilevano la clausola IN e la traducono.

In tutti i DBMS che ho testato, l'alias è valido solo all'interno di ()

A proposito, puoi riscrivere la query come:

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

E, per rispondere alle tue domande:

  1. Si
  2. Si
  3. Si

Altri suggerimenti

Stai calpestando un territorio complicato, noto come "sottoquery correlate". Dal momento che non abbiamo informazioni dettagliate sulle tue tabelle e sulle strutture chiave, alcune delle risposte possono essere solo "forse".

Nella query IN iniziale, la notazione sarebbe valida indipendentemente dal fatto che OtherTable contenga una colonna NameID (e, in effetti, se OtherDesc esiste come colonna in Table o OtherTable - che non è chiaro in nessuno dei tuoi esempi, ma presumibilmente è una colonna di OtherTable). Questo comportamento è ciò che trasforma una sottoquery correlata in una sottoquery correlata. È anche una fonte normale di angoscia per le persone quando si imbattono per la prima volta - inevitabilmente per caso. Poiché lo standard SQL impone il comportamento dell'interpretazione di un nome nella sottoquery come riferimento a una colonna nella query esterna se non c'è una colonna con il nome rilevante nelle tabelle menzionate nella sottoquery ma c'è una colonna con il nome pertinente nelle tabelle menzionate nella query (principale) esterna, nessun prodotto che desidera rivendicare la conformità (a questo bit) dello standard SQL farà qualcosa di diverso.

La risposta al tuo Q1 è "dipende", ma dati i presupposti plausibili (NameID esiste come colonna in entrambe le tabelle; OtherDesc esiste solo in OtherTable), i risultati dovrebbero essere gli stessi in termini di set di dati restituito, ma potrebbe non essere equivalente in termini di prestazioni.

La risposta al tuo Q2 è che in passato utilizzavi un DBMS inferiore se non difettoso. Se supporta EXISTS, il DBMS potrebbe comunque lamentarsi della cardinalità del risultato.

La risposta al tuo Q3 applicata alla prima query EXISTS è & t; t è disponibile come alias in tutta l'istruzione, ma o è disponibile solo come alias tra parentesi " ;. Come applicato alla tua seconda casella di esempio - con AND che collega due sottoselezioni (la seconda delle quali manca la parentesi aperta quando la sto guardando), allora "è disponibile come alias in tutta l'istruzione e si riferisce alla stessa tabella, ma ci sono due alias diversi entrambi etichettati 'o', uno per ogni sottoquery '. Si noti che la query potrebbe non restituire dati se OtherDesc è univoco per un determinato valore NameID in OtherTable; in caso contrario, richiede due righe in OtherTable con lo stesso NameID e i due valori OtherDesc per ogni riga nella tabella con quel valore NameID.

  1. Specifico per Oracle: quando si scrive una query utilizzando la clausola IN, si indica all'ottimizzatore basato su regole che si desidera che la query interna guidi la query esterna. Quando si scrive EXISTS in una clausola where, si indica all'ottimizzatore che si desidera eseguire prima la query esterna, utilizzando ciascun valore per recuperare un valore dalla query interna. Vedi " Differenza tra IN ed EXISTS nelle sottoquery " .
  2. Probabilmente.
  3. Alias ??dichiarato all'interno della subquery vive all'interno della subquery. A proposito, non credo che il tuo esempio con 2 subquery AND sia SQL valido. Intendevi UNIONE invece di AND?

Personalmente userei un join, piuttosto che una sottoquery per questo.

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

È difficile generalizzare che EXISTS sia sempre meglio di IN. Logicamente, in tal caso, la comunità SQL avrebbe sostituito IN con EXISTS ... Inoltre, tieni presente che IN ed EXISTS non sono gli stessi, i risultati potrebbero essere diversi quando usi i due ...

Con IN, di solito è una scansione di tabella completa della tabella interna una volta senza rimuovere NULL (quindi se nella tabella interna sono presenti NULL, IN non rimuoverà NULL per impostazione predefinita) ... Mentre EXISTS rimuove NULL e in caso di subquery correlata, esegue la query interna per ogni riga dalla query esterna.

Supponendo che non ci siano NULL ed è una query semplice (senza correlazione), EXIST potrebbe funzionare meglio se la riga che trovi non è l'ultima riga. Se si tratta dell'ultima riga, potrebbe essere necessario che EXISTS esegua la scansione fino alla fine come IN .. prestazioni così simili ...

Ma IN ed EXISTS non sono intercambiabili ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top