View Full Version : [access]Problema query con 'NOT LIKE'
silvia_m
09-07-2009, 13:31
Salve, sto lavorando ad un db di ricette con access e vorrei creare una query di ricerca delle ricette che NON contengano un determinato ingrediente ma che facciano parte di una certa categoria (es. tutte le ricette del tipo Biscotti che non contengono ricotta).
Le tabelle sono così strutturate:
- ricetta (id, id_tipo (FK))
- ingredienti (id)
- ingredientiRicetta (ID,id_ricetta (FK),id_ingredienti (FK))
- tipo (id)
ho creato una query con il not like ma non funziona perché mi esclude l’ingrediente (selezionato come parametro esterno) ma non la ricetta che lo contiene.
Come potrei risolvere questo problema?
Grazie in anticipo
Ciao
Silvia
silvia_m
09-07-2009, 14:59
la query è questa, ma considera che ci sono anche altre tabelle coinvolte:
SELECT DISTINCTROW [Indice ricette].id, [Indice ricette].titolo, [Indice ricette].pagina, dox.descrizione, tipologia.tipologia, [Indice ricette].foto, [Indice ricette].istruzioni
FROM Ingredienti INNER JOIN ((dox INNER JOIN (tipologia INNER JOIN [Indice ricette] ON tipologia.id_tipo = [Indice ricette].tipologia) ON dox.id_dox = [Indice ricette].dox) INNER JOIN IngredientiRicetta ON [Indice ricette].id = IngredientiRicetta.IDRicetta) ON Ingredienti.IDIngrediente = IngredientiRicetta.IDIngrediente
WHERE (((Ingredienti.Ingrediente) Not Like ("*" & [param] & "*")) AND (([Indice ricette].tipologia)=[param2])) OR ((([Indice ricette].tipologia1)=[param2])) OR ((([Indice ricette].tipologia2)=[param2]));
Devi scrivere una query a mano, non con il compositore di Access.
Dovrai scrivere una query che in Italiano suona come:
Selezionare tutte le ricette che facciano parte di una categoria X data, ma che non contengano neppure una volta l'ingrediente Y.
Dove quel "neppure una volta" si traduce con la clausola NOT EXISTS
Qualcosa come
SELECT * FROM RICETTE
WHERE categoria = 'X'
AND NOT EXISTS (
SELECT 1 FROM Ingredienti WHERE Ricette.IDRicetta=Ingredienti.IDRicetta
AND Ingredienti.Nome LIKE 'asdf%'
)
silvia_m
09-07-2009, 15:15
ci avevo provato senza il compositore, usando una select dentro una select. non conoscevo però il costrutto 'not exists'..
ci provo subito...
in ogni caso grazie!!!!
Salve, sto lavorando ad un db di ricette con access e vorrei creare una query di ricerca delle ricette che NON contengano un determinato ingrediente ma che facciano parte di una certa categoria (es. tutte le ricette del tipo Biscotti che non contengono ricotta).
Le tabelle sono così strutturate:
- ricetta (id, id_tipo (FK))
- ingredienti (id)
- ingredientiRicetta (ID,id_ricetta (FK),id_ingredienti (FK))
- tipo (id)
Basandomi strettamente sullo schema del DB, e sulla domanda specifica, eviterei l'uso del Like.
Dal momento che hai giustamente definito una tabella di raccordo IngredientiRicetta, per tagliare la relazione Molti-Molti tra
Ricetta e Ingredienti, usiamo quella.
Inoltre noto che in pratica i tuoi vari id sono chiavi e al tempo stesso descrizione dell'entità che rappresentano ( in pratica non fai un id numerico + descrizione-testo ), perciò la risolverei così :
SELECT DISTINCT Ricetta.id, Ricetta.id_tipo FROM Ricetta, IngredientiRicetta
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = 'ricotta' )
Prova... ;)
silvia_m
10-07-2009, 07:35
Siete fantastici!!!!!! Grazie!!!!!
Non conoscevo la clausola EXISTS che invece mi ha risolto tutto!
P.S. Per Marco: la clausola like la devo lasciare perchè la ricerca tra gli ingredienti è la più varia (es. esiste farina ma anche farina tipo 00)
Ecco la query finalmente funzionante...
SELECT [Indice ricette].id, [Indice ricette].titolo
FROM [Indice ricette]
WHERE [Indice ricette].tipologia=[param2] or ([Indice ricette].tipologia1=[param2] or [Indice ricette].tipologia2=[param2])
and not exists
(select 1 from ingredienti, ingredientiricetta
where ingredienti.idingrediente=ingredientiricetta.idingrediente
and ingredienti.ingrediente like '*' & [param] & '*');
silvia_m
10-07-2009, 10:29
Basandomi strettamente sullo schema del DB, e sulla domanda specifica, eviterei l'uso del Like.
Dal momento che hai giustamente definito una tabella di raccordo IngredientiRicetta, per tagliare la relazione Molti-Molti tra
Ricetta e Ingredienti, usiamo quella.
Inoltre noto che in pratica i tuoi vari id sono chiavi e al tempo stesso descrizione dell'entità che rappresentano ( in pratica non fai un id numerico + descrizione-testo ), perciò la risolverei così :
SELECT DISTINCT Ricetta.id, Ricetta.id_tipo FROM Ricetta, IngredientiRicetta
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = 'ricotta' )
Prova... ;)
...come non detto...
non funziona bene perchè la descrizione dell'ingrediente sta nella tabella ingrediente... mi dà molti più record di quanti me ne aspetti....:muro:
...come non detto...
non funziona bene perchè la descrizione dell'ingrediente sta nella tabella ingrediente... mi dà molti più record di quanti me ne aspetti....:muro:
Ma di cosa hai bisogno, di un elenco di ricette o di un elenco di ingredienti?
silvia_m
10-07-2009, 10:49
Ma di cosa hai bisogno, di un elenco di ricette o di un elenco di ingredienti?
elenco di ricette (selezionate per tipo) che non contengano un determinato ingrediente...
...come non detto...
non funziona bene perchè la descrizione dell'ingrediente sta nella tabella ingrediente... mi dà molti più record di quanti me ne aspetti....:muro:
Invece funziona. :)
Se vuoi posto un DB Access di prova che lo dimostra.
Bisogna solo intendersi sullo schema del DB. Tu hai postato questo schema :
- ricetta (id, id_tipo (FK))
- ingredienti (id)
- ingredientiRicetta (ID,id_ricetta (FK),id_ingredienti (FK))
- tipo (id)
Se in Ingredienti c'è un solo campo "id", mi sembra chiaro che non può essere un id numerico, sennò gli ingredienti sarebbero numeri puri, perciò ho ipotizzato che le tue chiavi primarie ( e relative FK ) fossero di tipo testo e contenessero il nome stesso ( che deve essere univoco ) dell'ingrediente, o della ricetta, e così via...
Come già scritto, ho postato quella query attenendomi fedelmente a quello schema del DB, se ora lo schema del DB è cambiato dovrai adattare la query di conseguenza...
In ogni caso è sempre difficile suggerire query di qualsiasi genere, finchè non è chiaro e definito una volta per tutte lo schema. ;)
silvia_m
10-07-2009, 11:06
Invece funziona. :)
Se vuoi posto un DB Access di prova che lo dimostra.
Bisogna solo intendersi sullo schema del DB. Tu hai postato questo schema :
- ricetta (id, id_tipo (FK))
- ingredienti (id)
- ingredientiRicetta (ID,id_ricetta (FK),id_ingredienti (FK))
- tipo (id)
Se in Ingredienti c'è un solo campo "id", mi sembra chiaro che non può essere un id numerico, sennò gli ingredienti sarebbero numeri puri, perciò ho ipotizzato che le tue chiavi primarie ( e relative FK ) fossero di tipo testo e contenessero il nome stesso ( che deve essere univoco ) dell'ingrediente, o della ricetta, e così via...
Come già scritto, ho postato quella query attenendomi fedelmente a quello schema del DB, se ora lo schema del DB è cambiato dovrai adattare la query di conseguenza...
In ogni caso è sempre difficile suggerire query di qualsiasi genere, finchè non è chiaro e definito una volta per tutte lo schema. ;)
Hai ragione, scusate...:doh:
la tabella ingredienti (id, descrizione)
es, id=1 desc=farina tipo 0
id=2 desc=farina tipo 00 ecc, ecc
ed ecco perchè ho necessità di usare il like...
Hai ragione, scusate...:doh:
la tabella ingredienti (id, descrizione)
es, id=1 desc=farina tipo 0
id=2 desc=farina tipo 00 ecc, ecc
ed ecco perchè ho necessità di usare il like...
Allora, ammettendo che questa sia l'unica modifica allo schema precedente :
SELECT DISTINCT Ricetta.id, Ricetta.id_tipo
FROM Ricetta, IngredientiRicetta, Ingredienti
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = Ingredienti.id
AND Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta, Ingredienti
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = Ingredienti.id
AND Ingredienti.descrizione LIKE 'ricotta' );
A ri-prova... ;)
silvia_m
10-07-2009, 11:35
non risponde... rimane in esecuzione e basta...
non risponde... rimane in esecuzione e basta...
Da me funziona, ma evidentemente ci sono ancora differenze di schema che non hai chiarito ( giudicando dalla query al tuo post #3... ).
Quando si fanno domande come la tua deve essere CHIARO lo schema, sennò è tutto inutile.
Altro consiglio : evita gli spazi nelle definizioni a livello del DB :
[Indice ricette] >> IndiceRicette, o Indice_ricette.
silvia_m
10-07-2009, 13:03
Funziona!
Ho solo dovuto togliere
WHERE [Indice ricette].tipologia=[param2] or ([Indice ricette].tipologia1=[param2] or [Indice ricette].tipologia2=[param2])
la parte in rosso (sono campi che ho ereditato dalla vecchia versione di access che non aveva i campi multivalore).
Funziona perfettamente cercando per tipo principale!
GRAZIE!!!!!
P.S. Per gli spazi nel nome tabella, non sai quanto li sto maledicendo.....
...peccato che per access non esista un bel refactor....
P.S. Per gli spazi nel nome tabella, non sai quanto li sto maledicendo.....
Eh, lo so... Se ne accorgono tutti quando è troppo tardi... :D
Per avere un elenco di ricette, non bisogna fare la JOIN con gli ingredienti.
Dovrebbe essere sufficiente la
SELECT * FROM Ricetta
WHERE Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = 'ricotta' )
Per avere un elenco di ricette, non bisogna fare la JOIN con gli ingredienti.
Dovrebbe essere sufficiente la
SELECT * FROM Ricetta
WHERE Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = 'ricotta' )
Ma poi lo schema è cambiato, perciò IngredientiRicetta.id_ingredienti è diventato un numero ( FK di id su Ingredienti ). Il nome dell'ingrediente adesso sta in Ingredienti.descrizione... ;)
Ma poi lo schema è cambiato, perciò IngredientiRicetta.id_ingredienti è diventato un numero ( FK di id su Ingredienti ). Il nome dell'ingrediente adesso sta in Ingredienti.descrizione... ;)
Ok. Scopiazzo meglio allora
SELECT *
FROM Ricetta
WHERE Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta, Ingredienti
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = Ingredienti.id
AND Ingredienti.descrizione LIKE 'ricotta' );
Ok. Scopiazzo meglio allora
SELECT *
FROM Ricetta
WHERE Ricetta.id_tipo = 'Biscotti'
AND NOT EXISTS ( SELECT 1 FROM IngredientiRicetta, Ingredienti
WHERE Ricetta.id = IngredientiRicetta.id_ricetta
AND IngredientiRicetta.id_ingredienti = Ingredienti.id
AND Ingredienti.descrizione LIKE 'ricotta' );
Sì, meglio così. :)
silvia_m
13-07-2009, 08:00
Ho aggiornato la query con i vostri ultimi suggerimenti e va alla grande!
Grazie ragazzi!!!!!!!!:) :) :) :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.