Condividi:        

sql: "left join" e "not in"

Hai problemi con i file Zip, vuoi formattare l'HD, non sai come funziona FireFox? O magari ti serve proprio quel programmino di cui non ricordi il nome! Ecco il forum dove poter risolvere i tuoi problemi.

Moderatori: Dylan666, hydra, gahan

sql: "left join" e "not in"

Postdi pjfry » 02/02/05 17:21

allora... ho paura che sarà difficile da spiegare...
oggi dovendo fare su oracle una query + avanzata del solito mi sono dovuto decidere ad utilizzare la 'left join'. alla fine la query ritorna + o meno quello che vorrei ma ho un problema.

mettiamo che ho 3 tabelle, A B e C, legati da una colonna x. voglio tutti gli elementi di A legati a B e non legati a nessuno, ma non quelli legati a C.
come si fa?
select * from A left join B on A.x=B.x where A.x NOT IN (select x from C)

così dovrebbe funzionare ma la NOT IN è lentissima, vero? c'è un modo per condizionare la left join con un not? non saprei dove metterlo :roll:
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Sponsor
 

Query SQL

Postdi infinito1971 » 03/02/05 09:31

Ciao pjfry,
da quanto dici, sembra che la tabella B non giochi un ruolo particolare (sei interessato a tutti gli elementi di A) ma poi vuoi che non siano nella tabella C; allora potresti provare in uno dei seguenti due modi (il primo dei quali più veloce):
Codice: Seleziona tutto
SELECT A.x FROM A LEFT JOIN B ON A.x=B.x LEFT JOIN C ON A.x=C.x where C.x_c IS NULL

Codice: Seleziona tutto
SELECT x FROM A WHERE x NOT IN (SELECT x FROM C)

Un saluto,
infinito1971
Questo business è binario: o sei 1 o sei 0, vivo o morto, non esistono secondi classificati!
Avatar utente
infinito1971
Utente Senior
 
Post: 532
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi pjfry » 03/02/05 09:56

in realtà B mi serve, perchè la select oltre ad alcuni campi di A deve selezionare anche B.name .
inoltre ovviamente non ho almeno 5 'B' e altrettante 'C', + altri casini qua e la :aaah

Codice: Seleziona tutto
SELECT A.x FROM A LEFT JOIN B ON A.x=B.x LEFT JOIN C ON A.x=C.x where C.x_c IS NULL

non avevo pensato ad una cosa del genere... però non capisco C.x_c :-? è una sintassi particolare o l'hai messo solo per farmi capire?

grazie :)
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Errore

Postdi infinito1971 » 03/02/05 10:11

Scusami, nel ricopiare ho commesso un errore... :P
Il codice è il seguente:
Codice: Seleziona tutto
SELECT A.x FROM A LEFT JOIN B ON A.x=B.x LEFT JOIN C ON A.x=C.x where C.x IS NULL

Ciao,
infinito1971
Questo business è binario: o sei 1 o sei 0, vivo o morto, non esistono secondi classificati!
Avatar utente
infinito1971
Utente Senior
 
Post: 532
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi infinito1971 » 03/02/05 10:13

Ovviamente attendo notizie per sapere com'è andata... ;)

bye
Questo business è binario: o sei 1 o sei 0, vivo o morto, non esistono secondi classificati!
Avatar utente
infinito1971
Utente Senior
 
Post: 532
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi pjfry » 03/02/05 10:40

non va... perchè (lo sapevo che sarebbe stato difficile spiegarlo :D ) io vorrei eliminare gli elementi legati SOLO a C, non tutti quelli legati a C. probabilmente a questo punto non va bene neanche la not in... fammi sapere se ti viene in mente qualcosa, ma ormai è + che altro per curiosità perchè si sono accontentati del risultato con qualche riga in + :D
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Re: sql: "left join" e "not in"

Postdi archimede » 03/02/05 11:20

pjfry ha scritto:mettiamo che ho 3 tabelle, A B e C, legati da una colonna x. voglio tutti gli elementi di A legati a B e non legati a nessuno, ma non quelli legati a C.
pjfry ha scritto:io vorrei eliminare gli elementi legati SOLO a C, non tutti quelli legati a C.
Eh si, non ti sei proprio spiegato, almeno io non ti seguo: puoi fare un piccolo esempio concreto?
archimede
Moderatore
 
Post: 2851
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi pjfry » 03/02/05 11:30

effettivamente volevo semplificare ma così non si capisce il problema :aaah
io ho una tabella che contiene i legami!
mettiamo L con 2 colonne, la prima colonna (l1) è chiave di A, la seconda (l2) è chiave di B o C.
+ o - è così:
select A.a1, B.b1 from A left join L
left join B on L.l2=B.l2
on A.x=L.x

in questo modo ottengo tutti gli elementi di A, e per quelli legati a B vedo il valore B.b1. il problema è che se ce ne sono alcuni legati anche a C avrò + righe uguali, questo vi torna?
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi archimede » 03/02/05 11:42

pjfry ha scritto:mettiamo L con 2 colonne, la prima colonna (l1) è chiave di A, la seconda (l2) è chiave di B o C.
Ma come fai a sapere quando l2 si riferisce a B o a C? Deduco che B e C NON possono contenere gli stessi valori...

Boh, tiro a indovinare:
Codice: Seleziona tutto
SELECT a.*, b.* FROM a,b,l WHERE a.x=l.l1 and b.x=l.l2;
HTH.

Alessandro
archimede
Moderatore
 
Post: 2851
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi pjfry » 03/02/05 11:51

archimede ha scritto:
pjfry ha scritto:mettiamo L con 2 colonne, la prima colonna (l1) è chiave di A, la seconda (l2) è chiave di B o C.
Ma come fai a sapere quando l2 si riferisce a B o a C? Deduco che B e C NON possono contenere gli stessi valori...
in realtà è scritto in un altro campo di L, ma speravo di non doverlo usare :D
archimede ha scritto:Boh, tiro a indovinare:
Codice: Seleziona tutto
SELECT a.*, b.* FROM a,b,l WHERE a.x=l.l1 and b.x=l.l2;

così ottengo solo quelli legati a B, ma io vorrei anche quelli non legati a B. la query che ho scritto prima funziona, però da quelle join ottengo troppe righe:

A.a1=pippo B.b1=pluto
A.a1=pippo B.b1=null
A.a1=topolino B.b1=null
la prima è ok, la terza pure (elemento di A non legato a nessuno)
la seconda deriva da un legame tra A e C, giusto? mi piacerebbe eliminarla...

(prima ho perso mezz'ora a formattare la query con tanti spazi per renderla leggibile e poi mi sono scordato il code :aaah :aaah )
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi archimede » 03/02/05 11:58

pjfry ha scritto:così ottengo solo quelli legati a B, ma io vorrei anche quelli non legati a B. la query che ho scritto prima funziona, però da quelle join ottengo troppe righe:

A.a1=pippo B.b1=pluto
A.a1=pippo B.b1=null
A.a1=topolino B.b1=null
la prima è ok, la terza pure (elemento di A non legato a nessuno)
la seconda deriva da un legame tra A e C, giusto? mi piacerebbe eliminarla...
Senti, sei un caro ragazzo ma io comincio ad avere una certa età: perchè non mi aiuti postando la struttura REALE (con i nomi REALI) delle tabelle (la parte rilevante), 4 o 5 records di esempio ed il risultato che vorresti?
pjfry ha scritto:(prima ho perso mezz'ora a formattare la query con tanti spazi per renderla leggibile e poi mi sono scordato il code :aaah :aaah )
Eh, quando vi deciderete ad abilitare la modifica sarà sempre troppo tardi! :P

Alessandro
archimede
Moderatore
 
Post: 2851
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi pjfry » 03/02/05 15:02

perchè ovviamente è top secret, e poi è tanto incasinata che ci metterei + tempo a pulirla che ad inventarla come farò ora... e speriamo bene :roll:

diciamo che ho una tabella con i nomi di alcune persone, e + tabelle con degli hobby possibili (una con i cinema, una con i bar, una con le piscine...).
Codice: Seleziona tutto
NOMI
name   key
fry       7
archi    1
infinito  9

CINEMA
name    key
astor    11
odeon   13

BAR
name         key
bar't          25


poi c'è la mitica tabella L che lega il tutto:
Codice: Seleziona tutto
L
key1 key2 type2
7       11    CINEMA
7       25    BAR
1       13    CINEMA


io voglio una lista di tutti gli utenti, con i cinema che frequentano ma non i bar.

Codice: Seleziona tutto
select utenti.name, cinema.name from utenti left join (L
left join cinema on L.key2=cinema.key)
on utenti.key=L.key1


dovrebbe ritornare:
Codice: Seleziona tutto
fry       astor
fry        null
archi    odeon
infinito   null

insomma c'è un "fry null" di troppo derivante dal fatto che fry va al bar ma non interessa a nessuno
:D

forse si potrebbe risolvere usando il campo type di L? oggi non ho tempo di provare
:roll:

grazie ;)
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi infinito1971 » 03/02/05 15:48

Scusa e se alla fine aggiungi: where Cinema.name is not null ??

bye,
infinito1971
Questo business è binario: o sei 1 o sei 0, vivo o morto, non esistono secondi classificati!
Avatar utente
infinito1971
Utente Senior
 
Post: 532
Iscritto il: 01/08/02 21:22
Località: Napoli

Postdi pjfry » 03/02/05 15:53

faccio fuori fry ma anche infinito che invece deve apparire nella lista :)
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi archimede » 03/02/05 15:57

io voglio una lista di tutti gli utenti, con i cinema che frequentano ma non i bar.
Solo quelli che vanno al cinema o tutti anche se non vanno al cinema (mettendo null il nome del cinema)? Scusa ma non mi pare la stessa cosa: la tua select dovrebbe tornare due o tre records?

Mi sembra un po' incasinata come struttura, comunque...

Solo al cinema:
Codice: Seleziona tutto
select utenti.name, cinema.name from utenti, cinema, L where L.key2=cinema.key AND utenti.key=L.key1
Tutti:
Codice: Seleziona tutto
select utenti.name, (select cinema.name from cinema, L where cinema.key=L.key2 AND utenti.key=L.key1) from utenti;
HTH.

Alessandro
archimede
Moderatore
 
Post: 2851
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi pjfry » 03/02/05 16:13

archimede ha scritto:
io voglio una lista di tutti gli utenti, con i cinema che frequentano ma non i bar.
Solo quelli che vanno al cinema o tutti anche se non vanno al cinema (mettendo null il nome del cinema)? Scusa ma non mi pare la stessa cosa: la tua select dovrebbe tornare due o tre records?

Mi sembra un po' incasinata come struttura, comunque...

Solo al cinema:
Codice: Seleziona tutto
select utenti.name, cinema.name from utenti, cinema, L where L.key2=cinema.key AND utenti.key=L.key1
Tutti:
Codice: Seleziona tutto
select utenti.name, (select cinema.name from cinema, L where cinema.key=L.key2 AND utenti.key=L.key1) from utenti;
HTH.

Alessandro

tutti, anche se non vanno al cinema, mettendo null il nome del cinema.
quindi la 1 non va bene (e poi era l'unica query che sapevo fare prima di imbarcarmi in questa impresa :lol: )
la 2 dovrei provarla, non ho mai usato una sintassi del genere :eeh:

la struttura ovviamente non l'ho inventata io, ma è questa query che è un po' particolare rispetto alle solite :roll:
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi archimede » 03/02/05 16:20

pjfry ha scritto:la 2 dovrei provarla, non ho mai usato una sintassi del genere :eeh:
Beh, se la vuoi provare forse è meglio che ti dò la versione corretta: :oops:
Codice: Seleziona tutto
select utenti.name, (select cinema.name from b, L WHERE cinema.key=L.KEY2 AND L.type2='CINEMA' AND utenti.key=L.key1) from utenti;
Alessandro
archimede
Moderatore
 
Post: 2851
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi archimede » 03/02/05 16:22

Cambronne!
Codice: Seleziona tutto
select utenti.name, (select cinema.name from cinema, L WHERE cinema.key=L.KEY2 AND L.type2='CINEMA' AND utenti.key=L.key1) from utenti;
Alessandro
archimede
Moderatore
 
Post: 2851
Iscritto il: 07/11/02 12:41
Località: Genova

Postdi pjfry » 04/02/05 14:46

dice 'single row subquery returns more than one row' :-?
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni

Postdi pjfry » 04/02/05 14:54

no, ora funziona...
appena ho tempo controllo l'esattezza dei dati, grazie cmq :D
Avatar utente
pjfry
Moderatore
 
Post: 8240
Iscritto il: 19/11/02 17:52
Località: terni


Torna a Software Windows


Topic correlati a "sql: "left join" e "not in"":


Chi c’è in linea

Visitano il forum: Nessuno e 99 ospiti