Newsgroup: it.comp.lang.delphi
Titolo: Ricerca in Database

Buongiorno a tutti,
Premetto di non essere esperto in database.
Dovrei effettuare in un database Firebird, una ricerca  in una determinata colonna, che contiene una o più date parole Es.
SELECT*FROM Nome_tabella WHERE nome_campo LIKE Parola da cercare.
Ho provato con LIKE e CONTAINING ma mi restituisce anche parole che contengono la parola cercata Es. se la parola cercata è "case" Mi restituisce "case,caserma,casella ecc", mentre io devo ottenere la parola esatta.
Ho usato anche Wildcards (% o [ ]) ma senza risultato. sarò sicuramente io che sbaglio la sintassi della query, sarei grato se qualcuno mi facesse un esempio.
Grazie in anticipo a chi mi vorrà rispondere.
Uso delphi 10.2 e accedo a Firebird con dbExpress.

Prova con =
SELECT*FROM Nome_tabella WHERE nome_campo = Parola da cercare. 


 Mi restituisce "case,caserma,casella ecc", mentre io devo ottenere la parola > esatta. 
 
Ciao.
Usare un DB senza troppa cognizione di causa è MALE.
Quindi, per prima cosa, non puoi prescindere dal leggere qualcosa sulla progettazione di un database relazionale ...
 
Infatti, Il tuo DB è SBAGLIATO E PROGETTATO MALE e DEVE ESSERE NORMALIZZATO. Ovvero, dovresti spezzare la tua tabella in 2
 
1) Tabella master con tutti i campi TRANNE quello che contiene le parole multiple, per comodità lo definisco "multiword".
 
2) Tabella detail con n record, dove N è il numero di parole contenute nel campo "multiword"
Questa tabella ha un suo ID come chiave primaria, un IDMASTER  che punta all'omonimo campo della tabella al punto 1 e un campo "singleword".
Su questa tabella metti un indice UNIQUE basato su masterid + singleword, in modo da evitare che per lo stesso record MASTER in detail ci sia più di un record con la stessa parola.
 
A quel punto,  la tua query diventa:
 
SELECT DISTINCT MASTER.MASTERID, MASTER.QUALCOSA, MASTER.QUALCOSALTRO. DETAIL.SINGLEWORD
JOIN DETAIL ON MASTER.MASTERID = DETAIL.MASTERID
WHERE DETAIL.SINGLEWORD = 'ES' 
 
...lo so, lo so...mo starai pensando "...ma che rottura di balle!!!".
Hai ragione, ma, per la mia esperienza, un db progettato MALE, scoppia.
Non è un SE, ma un QUANDO.
E poi, quando succede, ristrutturare un db pieno di dati si fa, ma oltre ad essere scomodo è PERICOLOSO.
Quindi, meglio iniziare BENE, in quanto:
 
a) se inizi con la merda finisci con la merda
b) la merda, piu' la rimescoli e piu' puzza.
 
 
A.
 
 


Scusa, sono curioso, ma come hai fatto a capire che il db è progettato male e non è normalizzato?
???????????????????????????
Rivediamo i fatti dati.
Ha una tabella con un campo che contiene valori diversi, e fin qua questa è la norma (niente da normalizzare ne da riprogettare).
Deve fare una query su questa tabella e usa like o containing è giustamente il ritorno sara "case" "caseificio" ecc.
usando = il ritorno sarebbe solamente 'case',  e tu cosa fai?
lo incasini con una join (che tra l'altro dovrebbe essere "inner") solo perche hai capito (credo che solo tu hai compreso questo con i dati disponibili)
che il suo database e una merda?
Complienti, bell'aiuto.

 Ha una tabella con un campo che contiene valori diversi, 
 
Ecco.
 
A.


Ma ecco cosa?  Hai scritto una minchiata fattene una ragione.

 Hai scritto una minchiata 
 
Infatti la su query funziona.
 
A.


Su una tabella clienti la ragione sociale la metti la dove hai il codice ( e questo campo ha valori diversi) senza creare altre tabelle. 
Facendo come tu dici, nel caso dato, sarebbe di certo una cattiva progettazione.
Dovevi solo rispondere al quesito posto, non fare il saputello e l'esegeta, visto che altro non si conosce.

 Dovevi solo rispondere al quesito posto, 
 
..dovevi.... Chi sei, TU, per dirmi quello che devo o non devo fare...? 
 
Ah, poi un altra cosa. Questa è la tua risposta al quesito:
 
SELECT*FROM Nome_tabella WHERE nome_campo = Parola da cercare. 
 
risposta che ovviamente NON FUNZIONA, indovina un po perche'...
 
A.


Grazie per la risposta, ma forse mi sono spiegato male, non devo trovare il campo = alla parola, ma bensì trovare i campi che contengono una o più parole date.

Il giorno lunedì 25 settembre 2023 alle 07:20:24 UTC+2 paolocarfi ha scritto:

Non credevo di scatenare una così accesa controversia, ho fatto una semplice domanda, sicuramente da persona meno esperta di chi mi ha risposto. Comunque non posso riprogrammare il database che deve restare così come è, e su questo dovrei fare una ricerca dei campi che contengono una o più parole date. Certamente ci sarà qualcuno così esperto da risolvere il problema, indicando una query appropriata, ringrazio comunque chi saprà e vorrà indicarmi una soluzione.


puoi utilizzare la clausola IN 
       where campo in [valore1, valore2 ecc.] 
                  es: (['case','edifici','garage',ecc.])
Oppure farti una stored procedure dove all'interno puoi utilizzare varie query secondo le tue esigenze.
 


Grazie per la risposta, proverò a mettere in atto i suggerimenti.

 ho fatto una semplice domanda, sicuramente da persona meno esperta di chi mi ha risposto.
 
La prima volta che si affronta qualcosa di nuovo siamo tutti inesperti...io, ad esempio, non so NULLA di html5 e javascript, PER ORA...
L'unico modo per arrivare ad una "seconda volta" è passare dalla prima.
 
Tornando al tuo problema, 
Se i valori sono delimitati, tipo pipe , prenzi ovviamente con le pinze,  si potrebbe provare una cosa del tipo:
 
 
select * from tabella where 
campo STARTING WITH 'SE|'
or
CAMPO LIKE ('%|SE|%')
or 
Position('|SE', campo) = CHAR_LENGTH(campo-3)
 
la prima condizione becca quelli che iniziano con SE e dopo hanno altri valori.
la seconda condizione becca quelli che contegono SE in mezzo ad altri valori
la terza condizione è tosta.... dovrebbe beccare quelli che hanno come ultimo valore SE ma quel "3" (ovvero length(SE) + 1 per il delimitatore,,) ovviamente andrebbe parametrizzato e non so se funziona...
 
 
Un altra via : Firebird ha l'operatore SIMILAR TO che permette l'uso di regular expression:
 
https://www.firebirdsql.org/file/documentation/html/en/refdocs/fblangref25/firebird-25-language-reference.html#fblangref25-commons-predsiimilarto
 
 
ma qua non ti so aiutare in quanto non le conosco... puoi vedere qualcosa qua:
 
https://regexr.com/
 
 
Se poi non sei vincolato a fare tutto via SQL,  fai una query con like e poi ti devi inventare qualche post elaborazione.
 
1) avrai un TClientDataset avente gli stessi campi della tua tabella
 
2) fai la query select * from tabella where campo like '%SE%' usando una TSQLQuery
 
3) chiudi e resetti il TClientDataset
 
4) cicli sui record restituiti; per ogni record controlli se il campo con piu valori contiene esattamente "SE"
 
4a) se il record contiene esattamente "SE", vai in append di un record sul TClientDataset e popoli tutti i campi, poi fai una post.
 
4b) se il record *non* contiene esattamente "SE",  lo scarti e e non fai nulla
 
4) sul tuo form o quello che è, mostrerai i dati presi NON dalla TSQLQuery ma da TClientDataset
 
Concordi con me  che avere una seconda tabella come dicevo in una precedente risposta avrebbe reso tutto più sempice...?
 
A.


Ti ringrazio per la risposta dettagliata, credo di avere abbastanza per "impazzire", vedrò di studiare per quel che posso, e arrivare alla soluzione del problema. sicuramente con una seconda tabella sarebbe stato più semplice, però non mi è possibile. per quanto riguarda le regular expression sono proprio a zero, ma vedrò cosa riesco a fare.

 per quanto riguarda le regular expression sono proprio a zero, ma vedrò cosa riesco a fare.
 
Ti capisco. Sono molto potenti ma poco leggibili se non le hai studiate bene... :-|
 
 
A.

Ciao Alberto,
   scusami ... mi sono perso nella discussione ...
 
Forse ho capito male .... ma Giovanni chiedeva com'era possibile fare una ricerca su una tabella dove "qualunque" campo del record contiene una data chiave di ricerca.
 
Un qualcosa come
 
Select * from mytable where TUTTI_I_CAMPI like '%qualcosa%'
 
Come si fa a dire "TUTTI_I_CAMPI" ?
 
Scusate se ho capto male ...
 
Ciao
Daniele 


Ciao Daniele, ti rispondo per evitare malintesi, Se leggi la mia richiesta, si riferisce a una "data colonna" non a tutte le colonne.

 Come si fa a dire "TUTTI_I_CAMPI" ? 
Da un punto di vista teorico questa cosa non ha molto senso.
Ha senso su un limitato numero di campi, ad esempio,  data una tabella con codice e descrizione,  l'utente digita un valore chiave e ti fai una cosa di questo tipo:
 
select * from tabella 
where 
codice like :p1
or
codice like :p2
 
dove p1 e p2 sono 2 parametri i cui valori assegni a runtime.
 
Teoria a parte, per una query che cerca su tutti i campi, su un relazionale ti tocca:
 
1) indicare n condizioni where specifice, dove n è il numero di campi della tabella, magari filtrato per tipo di dato...
Se l'utente cerca "pippo" una where su campi numerici non la puoi fare; per contro se l'utente cerca "123"  una where su campi numerici potrebbe avere senso.
 
2) aggiungere una sola condizione where del tipo:
select * from tabella 
where 
campo1 || campo2 || campo3 || ...campo n like :p1
 
Ma in entrambi i casi non puoi generalizzarla: DEVI specificare tutti i campim uno per uno, nome per nome.
 
Se invece usi un db NoSQL tipo MongoDb, credo (e sottlineo credo...) si possa definire una condizione che tenga conto di tutti i campi in modo implicito.
Ma ripeto, è solo un mio pensiero non supportato dai fatti: non conosco (ancora!) MongoDb o più in generale, database NoSQL.
 
A.

 > Grazie per la risposta, ma forse mi sono spiegato male, non devo trovare il campo = alla parola, ma bensì trovare i campi che contengono una o più parole date.
 
Niente di che ... tutto risolto al meglio ...
 
Ciao
Daniele
 
 

Credo si possano fare almeno due distinzioni:
 
a) al momento della progettazione del database era già evidente che si sarebbero dovute eseguire ricerche su almeno un campo per singole parole chiave
b) al momento della progettazione del database questa ricerca non era stata evidenziata come necessaria
 
Se siamo nella situazione a) probabilmente il database non è stato strutturato nel modo migliore per l'estrazione del dato richiesto
In questo caso darei ragione ad Alberto.
 
Se siamo nella situazione b) la domanda fatta può essere lecita: chiede se qualcuno ha una idea per estrarre l'informazione anche se il database non era stato predisposto per questa gestione. Non so voi, ma a me è capitato più volte di avere specifiche che sono cambiate nel tempo.
Al momento non credo sia gestibile solo con comandi sql diretti anche se non conosco nel modo specifico Interbase
Credo sia necessario processare a posteriori i record estratti con delle elaborazioni procedurali
 
Volendo aggiungere che sarebbe anche necessario gestire le combinazioni tipo "case", "casa", "caso" ... ma qui si apre un altro fronte di ragionamento.
 
Alessandro

 
Se DOPO, salta fuori il caso non previsto e ti tocca "tapparti il naso" e mettere una pezza del genere, ok.
Ma se poi, sulla pezza devi farci delle query, la pezza è peggiore del buco: DEVI, E SOTTOLINEO, DEVI, FARE RE FACTORING.
Alla fine vale il concetto zen "la via breve è la via lunga"... :-|
 
 
A.


Concordo al 1000%

 Comunque non posso riprogrammare il database che deve restare così come è,
 
Come mai?
 
Enrico

> Come mai? 
 
Perchè pur di risparmiare non si bada a spese.
 
A.