17. september 2015 - 15:49Der er
30 kommentarer og 1 løsning
Query find_in_set PHP/MySQL
Hej Eksperter
Jeg har en search query, som jeg ikke kan få til at virke optimal:
$query = 'SELECT id, navn, afdeling, underafdeling, area FROM mydatabase WHERE underafdeling LIKE "'.$search_string.'%" OR FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',') ) AND navn = "'.$navn.'" GROUP BY (afdeling) ORDER BY afdeling LIMIT 9';
Alt virker fint, indtil at jeg tilføjede FIND_IN_SET(), som skal sørge for at sammenligne indholdet af $search_string med den værdi som der er i AREA kolonnen i databasen.
AREA kolonnen indeholder en masse tekststrenge separaret med semi-kolon;
Er der nogen der kan sige mig, hvorfor ovenstående ikke fungerer?
Vi har aftalt andetsteds, at jeg skulle prøve at hjælpe her. Men jeg er ikke sikker på, at jeg kan gennemskue det. Lad mig se, om jeg forstår problemstillingen. Du har du har tekststrenge i underafdeling, og i area har du adskillige tekststrege. Du søger med to variabler, $search_string og $navn, og du vil have data udskrevet hvis $navn matcher og enten $search_string matcher i underafdeling eller findes i area. Er det korrekt forstået?
Så siger du, at alt virker fint indtil du tilføjer FIND_IN_SET... Så med queryen
$query = 'SELECT id, navn, afdeling, underafdeling, area FROM mydatabase WHERE underafdeling LIKE "'.$search_string.'%" AND navn = "'.$navn.'" GROUP BY (afdeling) ORDER BY afdeling LIMIT 9';
får du værdierne korrekt udskrevet hvis $navn matcher og $search_string matcher i underafdeling.
Hvad sker der så når du tilføjer FIND_IN_SET...? Hvis $search_string matcher i underafdeling burde du stadig få dataerne udskrevet, fordi FIND_IN_SET er en OR condition. Får du det i så fald korrekt udskrevet, eller hvad sker der? Du har vel prøvet denne query, hvor du ved, at $search_string findes i area:
'SELECT id, navn, afdeling, underafdeling, area FROM mydatabase WHERE FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',') ) '
Hvad sker der så?
Og så var det ikke det du spurgte om, men en datastruktur hvor du har adskillige elementer i et felt i tabellen synes ikke at være optimal. Hvor kommer indholdet af area feltet fra? Er der ikke mulighed for i stedet at gemme elementerne i en særskilt tabel?
Mht. navn og underafdeling skal du ikke tænke på det. Dét virker som det skal. Problemet er, at jeg gerne vil have $search_string til at lede efter matches i BÅDE underafdeling og area kolonnerne. Og i area kolonnen, skal der kigges på værdier separat fra semi-kolon.
Det var selvfølgelig muligt at gemme værdierne i en særskilt tabel. Men så ville de skulle oprettes hver i sær, med reference til den tilknyttede afdeling. Det ville tage meget lang tid.. Kan ikke lige gennemskue alternativet, må jeg indrømme.
Jeg noterer mig, at du har mellemrum mellem '$search_string' og kommaet i '$search_string' ,REPLACE(.... Måske er det ikke tilladt og det skal være '$search_string', REPLACE(....
Ellers må du vel gå trin for trin. Hvad jeg måske ville gøre var først at lave en test tabel med et par værdier hvor strengene i area er adskildt med kommaer og så prøve
SELECT id, navn, afdeling, underafdeling FROM mydatabase WHERE FIND_IN_SET('Arrangementer', area)
og se om du der får fejl. Hvis ikke, så prøv med din live tabel
SELECT id, navn, afdeling, underafdeling FROM mydatabase WHERE FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',') )
o.s.v.
Hvis du vil have værdierne i area i en særskilt tabel behøver du ikke lave en tabel for hver afdeling. Det findes der meget nemmere løsninger på, og så vidt jeg kan se, i stedet for at tage mere tid vil det spare dig tid, fordi du kun skal skrive hver værdi et sted i stedet for, som i din eksempel tabel, at du for hver borgerafdeling skal skrive 'Beredskab og akut hjælp; Bolig og byggeri; Familie, ......' Det kunne blive et emne for et særskilt spørgsmål hvis du har interesse.
Resultatet af ovenstående query er: Test;test2;test3- Antal:1
Hvis jeg ændre $variable til andet end Test;test2;test3, er siden blank :)
Men den skal egentlig kun udskrive den værdi den har fundet. Men det er fint at den kigger på dem "separeret". Men jeg er stadig ikke klar over, hvad fejlen er i den anden query.
1. Så FIND_IN_SET virker. Hvis din test tabel kun indeholder værdier der indeholder 'test' vil der naturligvis ikke komme noget resultat med en $variable med andet end 'test'.
2. Så må du jo tage næste trin, at udvide din test tabel med underafdeling og måske have fire rækker i tabellen, en hvor underafdeling er 'test' og afdeling er 'test;test2;test3', en hvor underafdeling er noget andet og afdeling er 'test;test2;test3', en hvor underafdeling er 'test' og afdeling er noget andet, og en hvor både underafdeling og afdeling ikke indeholder noget med 'test', lave $search_string = 'test', og køre
$query = 'SELECT * FROM WHERE underafdeling LIKE "'.$search_string.'%" OR FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',') ) GROUP BY (afdeling) ORDER BY afdeling LIMIT 9';
og se om det stadig går godt. Og så køre videre trin for trin indtil det ikke længere går godt.
$query = "SELECT * FROM offentligeinstitutioner WHERE underafdeling LIKE '$search_string' OR FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',')) AND navn = '$navn' GROUP BY (afdeling) ORDER BY afdeling LIMIT 9";
Dette giver ingen fejl! :) - Det er fremgang!
Men jeg får ingen resultater.. Synes ellers det ser rigtigt ud.
$query = "SELECT id,navn,afdeling,underafdeling,area FROM offentligeinstitutioner WHERE underafdeling LIKE '$search_string%' OR FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',')) AND navn = '$navn' GROUP BY (afdeling) ORDER BY afdeling LIMIT 9";
Mit eneste problem nu er, at jeg ønsker at udskrive den specifikke værdi, som der er matchet i kolonnen area. Den udskriver hele area rækken med værdier.
Lige nu ser det således ud: $display_function = $result['afdeling']." - ".$afdeling1." ".$result['area'];
Og så udskriver den som sagt afdeling og afdeling1 fint, men area udskriver mange værdier.
Din query er 'SELECT ....... area FROM ..... så naturligvis udskriver den area, altså hele feltet. Hvis du vil noget andet må du søge efter noget andet.
Nu står det mig ikke helt klart hvad du vil have udskrevet. Hvis du i tabellen har en række hvor for eksempel underafdeling er 'aaa' og area er 'bbb; ccc; ddd' og $search_string er 'bbb', så vil rækken blive selected. Så vil du formentligt ikke have udskrevet area feltet men alene 'bbb'. Men hvis $search_string er 'aaa' vil rækken også blive selected, fordi det matcher med underafdeling. Hvad vil du i det tilfælde have udskrevet som area? 'aaa' eller NULL eller ingenting?
Ja det er korrekt at bbb bliver selected. Men hvordan udskriver jeg så den specifikke værdi? Altså bbb. For når jeg udskriver area kommer alle værdier jo. Så mit problem er at den ikke udskriver én specifik værdi.
Den må gerne udskrive flere resultater. Problemet er bare at den uanset hvad udskriver hele area feltet.
Du svarede ikke på hele spørgsmålet. Hvis $search_string er 'aaa', en værdi der ikke indgår i area men som er lig med underafdeling, hvad skal der så udskrives for area? Det er vigtigt at vide hvad du har tænkt dig i dette tilfælde.
Vi miskommunikerede en gang mere. Din query er nu 'SELECT .... underafdeling, area FROM .....' Lad os antage, at din query resulterer i for eksempel ti matches, nogle hvor underafdelingen er lig med search strengen og nogle hvor search strengen forekommer i area, så vil resultatet nu for hver af de ti matches udskrive underafdelingen og hele area, det vil sige også i tilfælde af at search strengen forekommer i underafdelingen men ikke i area.
Nu vil du have noget andet end hele area udskrevet. Men du skal stadig for hver match have et eller andet udskrevet for area. Query resultater kommer, som du ved, i tabel form. Hvis search strengen forekommer i area, så vil du have search strengen udskrevet. Hvis search strengen ikke forekommer i area, så kan du enten få 'NULL' udskrevet eller '' (blank) eller 'Klodshans' eller .... Jeg går nu ud fra, at du vil have ''.
I så fald antager jeg (ikke testet), at en kode som det følgende vil give det ønskede resultat:
$query = "SELECT id,navn,afdeling,underafdeling, IF (FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',')), '$search_string', '') FROM offentligeinstitutioner WHERE underafdeling LIKE '$search_string%' OR FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',')) AND navn = '$navn' GROUP BY (afdeling) ORDER BY afdeling LIMIT 9";
Koden der er på websiden nu, er den du har skrevet i sidste indlæg. Jeg troede den søgte i "area", fordi jeg prøvede med "Moms" osv. Men det matchede jo også underafdelingerne.. Derfor der kom resultat. Det har ikke noget at gøre med "area".. Så det virker vidst ikke rigtig. For hvis du søger efter en specifik area-værdi, som ikke har noget tilfælles med en underafdelingen, så kommer der ingen resultater.
Nu skrev jeg noget vrøvl. Koden som jeg havde før den du skrev, virkede når man søgte på de specifikke værdier i areas. Det er den jeg har sat i funktion nu. Så det virker som det skal med den kode..
Problemet er bare, at den viser alle værdierne i area, som jeg har påpeget tidligere. Ellers virker det som det skal.
Jeg troede det virkede som det skal. Nu har jeg lige gennemtestet det. Det er fordi af den leder i UNDERAFDELING med $search_string%, så den kigger efter hvert enkelt ord i Underafdeling.
Hvis man finder noget som overhovedet ikke matcher med UNDERAFDELING, f.eks. "Gæld (restance)", så kommer der ingen resultater. Selvom dette findes i AREA. Det er din kode der er aktuel lige nu i scriptet.
Det er mystisk. Jeg forstod fra #11, at koden virkede, men at du ønskede at ændre den så ikke hele indholdet af area blev vist. Jeg foreslog så at erstatte 'SELECT ..... area...' med 'SELECT .... FIND_IN_SET.....' og ellers uændret kode. Du siger så, at hvis searchstrengen findes i area men ikke i underafdeling vises der ingen resultater.
Hvis du går tilbage til den kode du viste in #11, får du så resultater med en searchstreng der findes i area men ikke i underafdeling?
Tror jeg forstår det nu. Hvis du søger: "Satser", så kommer der et result frem. (Dog vises $result['area'] ikke? Altså resultatet). Den skulle jo faktisk gerne vise "Satser". Men det skal jo fungerer sådan, at den søger $search_string% i FIND_IN_SET, ellers skal man søge nøjagtigt det som svarer til en værdi i area. Jeg mener hvis man søger "Satse", må det gerne foreslå "Satser". Den må jo godt vise f.eks. 3 lignende resultater. Problemet er bare at så skal area explodes ";" fra semi-kolon og det er kun de lignende værdier der må vises? De skal jo ikke vises Resultat1;Resultat24;Resultat54, men: Resultat1 Resultat24 Resultat54
Hvis du søger efter: "Arbejdsmarkedsbidrag (AM-bidrag)" eller "Gæld (restance)", så kommer der ingen resultater. Her begynder jeg så at tro, at den ikke vil accepterer værdier der indeholder tegn såsom f.eks. en parentes. Alle andre værdier finder den resultater på.
Det vil du ikke svare på? Mit spørgsmål var (og det er essentielt for at forstå problemet) om den kode du i #11 sagde virkede, om den viste resultater, hvis søgestrengen forekom i area men ikke i underafdeling. Hvis du i #11 tog fejl og den ikke virkede i disse tilfælde, så er det den kode vi først skal tilbage til og få til at virke. Så prøv lige at skifte 'min kode' ud med den kode du viste i #11 og undersøg, om de problemer du nu har eksisterede allerede ved den kode, eller om alt virker efter hensigt med den kode (bortset fra at der vises hele indholdet fra area.) Vi er nødt til at kommunikere, ellers kommer vi ikke videre. Altså, gå venligst tilbage til før min kode og se om du så får de rigtige resultater.
Men svaret er: Ja, den viser resultater, koden i #11, selvom søgestrengen ikke forekommer i underafdeling. Og omvendt hvis søgestrengen forekommer i underafdeling men ikke i area. Og hvis den forekommer i begge, virker det også. Men IKKE når der er parenteser i søgestrengen.. og garanteret heller ikke andre tegn.
Din kode virker på samme måde som #11. Jeg kan ikke se nogle funktionsmæssige ændringer. Udover at $result['area'] værdierne ikke vises i din kode. Der vises intet fra area.
Der er dog én lille ting. Jeg ønsker at gøre sådan, at søgemaskinen kommer frem med forslag der minder om det man har skrevet. Dvs. en funktion som LIKE '$variabel%'. Dvs. skriver jeg satse og der er et result der hedder 'satser', så udskriver den denne værdi.
Nogle idéer til hvordan det kan løses?
Den nuværende query er: $query = "SELECT id,navn,afdeling,underafdeling, IF (FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',')), '$search_string', '') AS selectedAreas FROM offentligeinstitutioner WHERE navn = '$navn' AND underafdeling LIKE '$search_string%' OR FIND_IN_SET('$search_string' ,REPLACE(area, ';', ',')) GROUP BY (afdeling) ORDER BY afdeling LIMIT 9";
dounie, ja, jeg har været længe om at reagere. Så er det godt, at du i mellemtiden selv har fået det løst.
Nu stiller du et nyt problem op, søgeforslag undervejs. Det synes jeg er en god ide for dit formål. Selv kender jeg ikke ret meget til den slags, og jeg vil tro, at det efterhånden kun er mig der kikker på denne tråd. Du bør oplagt, for dette, oprette et nyt frisk spørgsmål der så vil blive set af alle, og så lukke dette spørgsmål (vel nok med eget svar.) Det er generelt en god ide og mest effektivt at oprette nye spørgsmål for nye problemer.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.