Domanda

Ho una domanda che praticamente esegue qualcosa di simile:

select a, b, c
from tab
where tab.state = 'A'
minus
select a, b, c
from tab
where tab.state = 'B'

In questo esempio, a, b, e c sono i campi chiave di questa tabella. state è anche una parte della chiave e sto cercando di trovare situazioni in cui c'è un record nello stato A e non nello stato B. C'è un altro campo (non nella chiave) su cui mi piacerebbe riferire, value, potrebbe essere diverso per lo stesso record in stati diversi. Esempio:

a  b  c  state  value
---------------------
1  1  1  A      12
1  2  2  A      1002
1  3  9  A      43
1  1  1  B      17.34
1  2  2  B      1002

In questo caso, sono interessato alla riga di cui è la chiave 1,3,9 dove lo stato è A. Mi piacerebbe anche ottenere il valore del value colonna, ma se provo:

select a, b, c, value
from tab
where tab.state = 'A'
minus
select a, b, c, value
from tab
where tab.state = 'B'

Quello che vorrei restituire è due righe:

a  b  c    value
----------------
1  1  1      12
1  3  9      43

Fondamentalmente, voglio avere value nel set di risultati, ma non partecipa al minus. Sento che mi manca qualcosa di ovvio qui, ma forse sono troppo stanco per ottenerlo ...;)

È stato utile?

Soluzione

Il modo ovvio per farlo è così:

select a, b, c, value
from tab
where tab.state = 'A' and not exists (
  select 1                          -- let the optimizer do its thing
  from tab ti
  where tab.state = 'B' and ti.a=tab.a and ti.b=tab.b and ti.c=tab.c)

Aggiungerei anche un distinct Nella query esterna se i dati possono avere doppi.

Altri suggerimenti

Puoi unirti a tutte le righe dove state = 'A' con quelli abbinati con state = 'B'...

SELECT t1.a, t1.b, t1.c, t1.value, t2.value v2
FROM (SELECT a, b, c, value FROM tab WHERE state = 'A') t1
     LEFT JOIN (SELECT a, b, c, value FROM tab WHERE state = 'B') t2
            ON t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c

... e poi scegli le righe dove non c'erano corrispondenze:

 SELECT a, b, c, value
 FROM ( /* previous query */ )
 WHERE v2 IS NULL
SELECT a,
  b,
  c,
  value
FROM tab tab1
INNER JOIN
  (SELECT a, b, c FROM tab WHERE tab.state = 'A'
  MINUS
  SELECT a, b, c FROM tab WHERE tab.state = 'B'
  ) tab2
ON tab1.a  = tab2.a
AND tab1.b = tab2.b
AND tab1.c = tab2.c 

Credo che il codice sopra farebbe il trucco.

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