View Full Version : [SQL] problema select
serbring
15-04-2010, 16:28
Ho una tabella e vorrei creare una query che mi ritorna tutti record in cui certo campo numerico è minore di quello fornito dall'utente. Vorrei che l'utente potesse decidere se filtrare i dati secondo questo campo oppure no, immettendo il valore Null. D'altro canto molti record assumono valori null. Quindi come posso fare ad avere tutti i record se l'utente fornisse in input il valore null?
yorkeiser
15-04-2010, 17:31
Devi essere un attimo piu specifico: in primis, che db stai usando?
Inoltre, per i record che nel db hanno il campo a NULL, vuoi che ti vengano restituiti o meno?
Ciao. Penso di avere capito il problema, che e' un problema classico.
Qualcosa del genere
Supponendo che il parametro utente sia @NomeCol, relativo alla colonne NomeCol della tabella,
SELECT * FROM Tabella
WHERE (CASE WHEN @NomeCol IS NOT NULL THEN NomeCol ELSE 1 END <
CASE WHEN @NomeCol IS NOT NULL THEN @NomeCol ELSE 2 END)
Occhio che nel primo pezzo c'e' un @ e nel secondo no.
Questo un abbozzo, migliorabile a seconda del dialetto SQL in questione.
Ma per esperienza ti assicuro che se passi attraverso il query composition, ovvero comporre una query dinamicamente a seconda dei parametri utente inseriti, otterrai risultati comunque sempre migliori, evitando di fare impazzire l'ottimizzatore che altrimenti molto probabilmente restituirebbe un piano di esecuzione penoso.
PS: Sistemi "moderni" come Hibernate o Linq2Entity sono facilmente pilotabili con il query composition, e restituiscono un SQL davvero buono.
serbring
15-04-2010, 20:11
Devi essere un attimo piu specifico: in primis, che db stai usando?
Inoltre, per i record che nel db hanno il campo a NULL, vuoi che ti vengano restituiti o meno?
uso access 2007, cmq sono un newbie. Non l'ho specificato perchè ero convinto che l'sql fosse un linguaggio standard
se io il parametro immesso dall'utente è NULL allora voglio mostrare tutti i record, se invece è diverso da NULL voglio mostrare tutti i record che nella colonna hanno il valore immesso dall'utente. Spero di essermi spiegato meglio
serbring
15-04-2010, 20:30
Ciao. Penso di avere capito il problema, che e' un problema classico.
Qualcosa del genere
Supponendo che il parametro utente sia @NomeCol, relativo alla colonne NomeCol della tabella,
SELECT * FROM Tabella
WHERE (CASE WHEN @NomeCol IS NOT NULL THEN NomeCol ELSE 1 END <
CASE WHEN @NomeCol IS NOT NULL THEN @NomeCol ELSE 2 END)
Occhio che nel primo pezzo c'e' un @ e nel secondo no.
Questo un abbozzo, migliorabile a seconda del dialetto SQL in questione.
Ma per esperienza ti assicuro che se passi attraverso il query composition, ovvero comporre una query dinamicamente a seconda dei parametri utente inseriti, otterrai risultati comunque sempre migliori, evitando di fare impazzire l'ottimizzatore che altrimenti molto probabilmente restituirebbe un piano di esecuzione penoso.
PS: Sistemi "moderni" come Hibernate o Linq2Entity sono facilmente pilotabili con il query composition, e restituiscono un SQL davvero buono.
scusami ma non devo fare un controllo sia se il valore immesso dall'utente è NULL, al che nella condizione where non ho nulla, e se ho un valore diverso da NULL dovrei avere una condizione del tipo where nomecol=input_val? Come mai hai messo la @ solo su una delle due righe?
scusami ma non devo fare un controllo sia se il valore immesso dall'utente è NULL, al che nella condizione where non ho nulla, e se ho un valore diverso da NULL dovrei avere una condizione del tipo where nomecol=input_val?
Se leggi bene e' proprio quanto succederebbe (A parte il minore come da te richiesto, e non l'uguale)
Se l'utente inserisce un valore nel parametro @NomeCol, la clausola WHERE viene trasformata in
WHERE NomeCol<@NomeCol
Se invecve @NomeCol dovessere valere NULL, allora la clausola WHERE viene trasformata in
WHERE 1<2
che e' sempre verificata, ed equivale ad ignorare la clausola stessa, ovvero estrarre tutti i record.
serbring
15-04-2010, 20:51
Se leggi bene e' proprio quanto succederebbe (A parte il minore come da te richiesto, e non l'uguale)
Se l'utente inserisce un valore nel parametro @NomeCol, la clausola WHERE viene trasformata in
WHERE NomeCol<@NomeCol
Se invecve @NomeCol dovessere valere NULL, allora la clausola WHERE viene trasformata in
WHERE 1<2
che e' sempre verificata, ed equivale ad ignorare la clausola stessa, ovvero estrarre tutti i record.
ahhh capito...l'ho provata e mi dice che c'è un errore di sintassi. evidenziandomi il primo when
Sembra che ACCESS non supporti la clausola CASE (Quasi standard e supportata da tutti gli altri DB Relazionali)
Prova a vedere se riuesci a cavartela con IIF o con SWITCH
...
Switch ( expression1, value1, expression2, value2, ... expression_n, value_n )
where expression can be a condition
p.e.
Switch (SupplierID=0 or SupplierID=1, "IBM", SupplierID=2, "HP", SupplierID=3, "Nvidia")
an access sql sample:
SELECT
Switch(zip='92789', 'west', zip Is Null, 'missing', zip>='96745', 'northwest', True, '*') AS [Searched Case]
FROM authors;
also you can use the IIF function:
iif ( condition, value_if_true, value_if_false )
PS: Se stai facendo qualcosa di piu' complesso del DB della tua cantina o del DB dei libri che hai prestato agli amici oppure quello dell'associazione EX-Alunni della tua scuola locale, ti consiglio di lasciare perdere ACCESS e passare a qualcosa di piu' serio e magari addirittura gratuito (PS: SQL-Server Express, Oracle Express, ma tanti altri). E se proprio dovessi decidere di cambiare, lascia stare MySql.
serbring
15-04-2010, 21:08
Sembra che ACCESS non supporti la clausola CASE (Quasi standard e supportata da tutti gli altri DB Relazionali)
Prova a vedere se riuesci a cavartela con IIF o con SWITCH
PS: Se stai facendo qualcosa di piu' complesso del DB della tua cantina o del DB dei libri che hai prestato agli amici oppure quello dell'associazione EX-Alunni della tua scuola locale, ti consiglio di lasciare perdere ACCESS e passare a qualcosa di piu' serio e magari addirittura gratuito (PS: SQL-Server Express, Oracle Express, ma tanti altri). E se proprio dovessi decidere di cambiare, lascia stare MySql.
sto facendo un'applicazione semplice e siccome avevo usato access 2 anni fà avevo pensato di usarlo di nuovo, solo che non mi ricordo più nulla....:(
Funzionante in access:
SELECT *
FROM Tabella
WHERE nomecampo<[inserisci valore]
AND nomecampo2<[inserisci valore];
e via così, ricordati il ';' alla fine e l'AND per concatenare le richieste sulle selezioni. Nomecampo sono i nomi delle colonne della tua tabella. Puoi aggiungere anche un ORDER BY nomecampo per averli ordinati :)
serbring
15-04-2010, 21:50
Sembra che ACCESS non supporti la clausola CASE (Quasi standard e supportata da tutti gli altri DB Relazionali)
Prova a vedere se riuesci a cavartela con IIF o con SWITCH
PS: Se stai facendo qualcosa di piu' complesso del DB della tua cantina o del DB dei libri che hai prestato agli amici oppure quello dell'associazione EX-Alunni della tua scuola locale, ti consiglio di lasciare perdere ACCESS e passare a qualcosa di piu' serio e magari addirittura gratuito (PS: SQL-Server Express, Oracle Express, ma tanti altri). E se proprio dovessi decidere di cambiare, lascia stare MySql.
ho usato questo codice
WHERE Switch ( [Forms]![Maschera]![combo_minpower] = "IS NULL", 2>1, [Forms]![Maschera]![combo_minpower] <> "IS NULL",Implement.[Min engine power (kW)]<[Forms]![Maschera]![combo_minpower] );
solamente che quando è NULL non mi viene restituito nulla
Le clausole CASE erano 2, le clausole SWITCH dovranno essere 2...
serbring
15-04-2010, 22:08
Le clausole CASE erano 2, le clausole SWITCH dovranno essere 2...
ho due clusole se null fai questo se non è null fai quest'altro......:confused:
Fatto salvo che non so come vengono passati i parametri sotto Access, e supponendo che un parametro possa essere chiamato
@parametro
io scriverei cosi'.
WHERE Switch ( @parametro = "IS NULL", 1, [Forms]![Maschera]![combo_minpower])
< Switch ( @parametro = "IS NULL", 2, @parametro)
(In realta', per come avevo detto prima, non lo scriverei comunque. Troverei un modo, se possibile, di comporre la query al volo a seconda dei parametri utente, includendo oppure no la clausloa where sul campo specifico)
E se proprio dovessi decidere di cambiare, lascia stare MySql.
Ciao, come mai deve lasciare stare Mysql?
Ps: ma Oracle Express è valido? io lo avevo installato e disinstallato nel giro di mezz'ora non trovavo documentazione.
Ciao, come mai deve lasciare stare Mysql?
Lento, non e' neppure SQL Standard, se non fai attenzione puoi violare le Foreign Keys, e non e' free come si puo' pensare in quanto non liberamente ridistribuibile, a differenza di altri fratelli maggiori.
Per cointinuare, l'azienda che ora ne possiede i diritti, Oracle, ha un prodotto concorrente tra i suoi assett, che e' proprio il suo principale, quello che gli da' da mangiare. Non so quindi quanto possa essere spinto o supportato in futuro.
Lento, non e' neppure SQL Standard, se non fai attenzione puoi violare le Foreign Keys, e non e' free come si puo' pensare in quanto non liberamente ridistribuibile, a differenza di altri fratelli maggiori.
Per cointinuare, l'azienda che ora ne possiede i diritti, Oracle, ha un prodotto concorrente tra i suoi assett, che e' proprio il suo principale, quello che gli da' da mangiare. Non so quindi quanto possa essere spinto o supportato in futuro.
Se è per questo neppure SQL-Server è standard. Almeno fino a qualche anno fa, era un dialetto tutto suo, magari ora è cambiato qualcosa.
A proposito di Oracle, avevo scritto un Postum Scriptum sopra, magari dopo il tuo commento, mi piacerebbe sapere il tuo punto di vista.
Comunque Mysql non morirà. Anzi, c'è parecchia carne sul fuoco:
http://punto-informatico.it/2858278/PI/News/oracle-celebra-nozze-mysql-innodb.aspx
Se è per questo neppure SQL-Server è standard. Almeno fino a qualche anno fa, era un dialetto tutto suo, magari ora è cambiato qualcosa.
Che io sappia e' sempre stato SQL92 standard. Almeno la versione 2000 lo era, prima non l'ho mai preso in mano.
Ci sono aggiunte, per fare aclune operazioni piu' comodamente (concetti peraltro diffusi in tutti i motori), ma le cose SQL92 standard sono sempre supportate.
A proposito di Oracle, avevo scritto un Postum Scriptum sopra, magari dopo il tuo commento, mi piacerebbe sapere il tuo punto di vista.
Oracle Express e' identico ad Oracle normale, a parte alcune limitazioni che non impattano nella stragrande maggioranza dei database anche commerciali.
Quindi la documentazione e' la stessa, e ce n'e' tanta da annegare.
Comunque Mysql non morirà. Anzi, c'è parecchia carne sul fuoco:
http://punto-informatico.it/2858278/PI/News/oracle-celebra-nozze-mysql-innodb.aspx
Chi vivra' vedra'. Comunque siamo OT.
serbring
16-04-2010, 11:11
Fatto salvo che non so come vengono passati i parametri sotto Access, e supponendo che un parametro possa essere chiamato
@parametro
io scriverei cosi'.
WHERE Switch ( @parametro = "IS NULL", 1, [Forms]![Maschera]![combo_minpower])
< Switch ( @parametro = "IS NULL", 2, @parametro)
ho risolto con questo codice:
WHERE Switch ([Forms]![Maschera]![combo_maxpowe] IS NULL,[Forms]![Maschera]![combo_minpower]>0, [Forms]![Maschera]![combo_maxpowe] <> "IS NULL",[Max engine power (kW)]<[Forms]![Maschera]![combo_maxpowe] );
grazie mille senza le tue indicazioni non ci sarei mai arrivato
domanda tecnica: è possibile avere in un campo numerico un vettore? Perchè uno di questi campi può assumere due valori numerici contemporaneamente.
(In realta', per come avevo detto prima, non lo scriverei comunque. Troverei un modo, se possibile, di comporre la query al volo a seconda dei parametri utente, includendo oppure no la clausloa where sul campo specifico)
in che senso devo trovare un modo di comporre la query al volo? Che in funzione di quello di cui ho bisogno mi creo la query di volta in volta? Considera che il database deve essere usata da persone di 60anni che non conoscono sicuramente access e quindi volevo creare una maschera in cui loro potessero fare certe selezioni
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.