Multi keywords search with SQL - sql

I'm using a search bar on my website based on keyup binding and ajax requests. It works fine but I would like my search engine to be able to have finner result with multi keywords management.
However I could not find any simple method to set up this kind of search method.
Does anyone knows how to set this up ?
Here is the actual SQL request that's being made:
if ($recherche !=""){
$req = $this->bdd->prepare("SELECT * FROM videos WHERE titre LIKE :recherche OR auteur LIKE :recherche UNION SELECT videos.id_video, videos.titre, videos.lien, videos.auteur, videos.date_upload FROM videos RIGHT JOIN mots_clefs ON videos.id_video = mots_clefs.id_video AND mots_clefs.mot_clef LIKE :recherche ORDER BY date_upload DESC LIMIT ".$start.", ".$limit);
$req->execute(array('recherche' => "%".$recherche."%"));
$result = json_encode($req->fetchAll(PDO::FETCH_ASSOC));
}
Request example:
SELECT * FROM videos WHERE titre LIKE '%word 1 word 2%' OR auteur LIKE '%word 1 word 2%' UNION SELECT videos.id_video, videos.titre, videos.lien, videos.auteur, videos.date_upload FROM videos RIGHT JOIN mots_clefs ON videos.id_video = mots_clefs.id_video AND mots_clefs.mot_clef LIKE '%word 1 word 2%' ORDER BY date_upload DESC LIMIT 0, 20);

You can execute the above query in a loop by passing one keyword at a time.
get the entire keyword list provided by the user into a sting.
Use string.Split() method by passing comma(,) as delimiter to get the list of the keywords into an array list.
loop through the array list and pass to the query.
Make sure you append the data fetched from the SQL into a data table or dataset and Not rewrite it.
string select = "SELECT * FROM [MyTable] WHERE [Title] LIKE '%" + strSearch.Replace(",", "%' OR [Title] LIKE '%") + "%'";

Related

cfsavecontent display double apostrophe in SQL statement

I have several OR in my SQL statement so I want to save a chuck of it in a cfsavecontent. Here is that part:
<cfsavecontent variable="checkDepartment">
<cfif #wrkDept# EQ #dept[2][1]#>
Department = 'Health' AND
<cfelse>
Department = '#wrkDept#' AND
</cfif>
</cfsavecontent>
But the error I get on the page shows 2 sets of apostrophes around the word Health.
SQL
SELECT COUNT(*) AS numItems
FROM IT_PROJECTS
WHERE
Department = ''Health'' AND
status = 'Cancelled'
Can anyone help me to only get a single apostrophe? Thanks
So this answer seems a lot more complicated than it really is. And without knowing specifically what your query looks like (re:OR conditions), I'm not really sure how to structure it. It can be better. The goal should be to make one single trip to your SQL server with the query that makes the most sense for the data you're trying to get. I'm not sure what you are trying to do with cfsavecontent, but I don't think you need it.
The bulk of my example query (https://trycf.com/gist/4e1f46bfa84a6748aced0f9ee8221c6d/acf2016?theme=monokai) is setup. I chose to go with a cfscript format, because as Redtopia said, I also find it much easier to build a dynamic query in cfscript.
After initial setup, I basically just script out the variables I'll use in my final queryExecute().
// Base query.
qry = "SELECT count(*) AS theCount FROM IT_PROJECTS WHERE 1=1 " ;
// This is our dynamic filter that we build below.
qfilter = {} ;
// Query options.
opts = { "dbtype":"query" } ;
After we have our base, I build up the dynamic part of the query. This is the part that will likely change quite a bit depending on your current needs and setup.
For the first part, I basically replaced your cfif with a ternary evaluation. I'm not sure how your data plays into the evaluation of dept or where that array comes from. But from there I build a basic included statement of the query and set up the queryparam values for it. Then I add a second check that will pick a different set of values for the query (currently based on even/odd seconds). Again, I'm not sure of the intent of your query here, so I just made something dynamic.
//////////// BUILD DYNAMIC FILTER ////////////
qdept = ( wrkDept == dept[2][1] ) ? 'Health' : wrkDept ;
/// This one is an included filter:
qry &= " AND department = :dpt AND status = :sts " ;
qfilter.dpt = {"value":qdept,"cfsqltype":"CFSQLVARCHAR"} ;
qfilter.sts = {"value":"Cancelled","cfsqltype":"CFSQLVARCHAR"} ;
/// Adding Dynamic ORs
// Dynamically set status based on even/odd seconds.
qStatus = ( now().second()%2==0) ? "Cancelled" : "Active" ;
qry &= " OR ( department = :dpt2 AND status = :sts2 ) " ;
qfilter.dpt2 = {value:"IT",cfsqltype:"CFSQLVARCHAR"} ;
qfilter.sts2 = {value:qStatus,cfsqltype:"CFSQLVARCHAR"} ;
This gives us a SQL string that looks like:
SELECT count(*) AS theCount
FROM IT_PROJECTS
WHERE 1=1
AND department = :dpt AND status = :sts
OR
( department = :dpt2 AND status = :sts2 )
With a SQL statement, the placement of AND and OR conditions can greatly impact the results. Use parenthesis to group conditions how you need them.
After we've built the query string, we just have to plug it and our queryparams into the queryExecute().
result = queryExecute( qry , qfilter , opts ) ;
And if we want to output our data, we can go:
writeOutput("There are " & result.theCount & " records." ) ;
Which gives us:
There are 8 records.
Again, I don't know what your main conditions look like. If you can give me an example of a query with a bunch of ORs and ANDs, I'll try to modify this for you.

Apply like function on an array is SQL Server

I am getting array from front end to perform filters according that inside the SQL query.
I want to apply a LIKE filter on the array. How to add an array inside LIKE function?
I am using Angular with Html as front end and Node as back end.
Array being passed in from the front end:
[ "Sports", "Life", "Relationship", ...]
SQL query is :
SELECT *
FROM Skills
WHERE Description LIKE ('%Sports%')
SELECT *
FROM Skills
WHERE Description LIKE ('%Life%')
SELECT *
FROM Skills
WHERE Description LIKE ('%Relationship%')
But I am getting an array from the front end - how to create a query for this?
In SQL Server 2017 you can use OPENJSON to consume the JSON string as-is:
SELECT *
FROM skills
WHERE EXISTS (
SELECT 1
FROM OPENJSON('["Sports", "Life", "Relationship"]', '$') AS j
WHERE skills.description LIKE '%' + j.value + '%'
)
Demo on db<>fiddle
As an example, for SQL Server 2016+ and STRING_SPLIT():
DECLARE #Str NVARCHAR(100) = N'mast;mode'
SELECT name FROM sys.databases sd
INNER JOIN STRING_SPLIT(#Str, N';') val ON sd.name LIKE N'%' + val.value + N'%'
-- returns:
name
------
master
model
Worth to mention that input data to be strictly controlled, since such way can lead to SQL Injection attack
As the alternative and more safer and simpler approach: SQL can be generated on an app side this way:
Select * from Skills
WHERE (
Description Like '%Sports%'
OR Description Like '%Life%'
OR Description Like '%Life%'
)
A simple map()-call on the words array will allow you to generate the corresponding queries, which you can then execute (with or without joining them first into a single string).
Demo:
var words = ["Sports", "Life", "Relationship"];
var template = "Select * From Skills Where Description Like ('%{0}%')";
var queries = words.map(word => template.replace('{0}', word));
var combinedQuery = queries.join("\r\n");
console.log(queries);
console.log(combinedQuery);

Replace Asterisk(*) with "anything" in SQL

I am having a tons of URL's in my database and want to filter them by user-defined string in format something/*/something, where * stands for "anything". So when user defines checkout/*/complete, it means it filters out url's like:
http://my_url.com/checkout/15/complete
http://my_url.com/checkout/85/complete
http://my_url.com/checkout/something/complete
http://my_url.com/super/checkout/something/complete
etc.
How do I do that in SQL? Or should I filter out all the results and use PHP to do the job?
My SQL request now is
SELECT * FROM custom_logs WHERE pn='$webPage' AND id IN ( SELECT MAX(id) FROM custom_logs WHERE action_clicked_text LIKE '%{$text_value_active}%' GROUP BY token ) order by action_timestamp desc
This filters out all the log messages with user-defined text in column action_clicked_text, but uses LIKE statement, which will not work with * inside.
You want like. Either:
where url like '%checkout/%/complete%'
to get the urls that match he pattern. Or:
where url not like '%checkout/%/complete%'
to get the other urls.

use a regex capture in a pgSQL select

I've never used a regex in SQL. If I capture something like this in javascript, how can I refer back to the capture in pgSQL like I can with the 2nd element in javascript match() method?
var str = 'thomas-var1="SOME VAL1" thomas=var2="SOME VAL2" thomas-var-3="the value i want" thomas-var-4="SOME_VAL4"';
var re = /thomas-var-3="(.+?)"/i;
var new_str = str.match(re);
console.log(new_str[1]);
How can I put that into a SELECT statement so that I can say something like, retrieving the value "the value i want" from thomas-var-3?
SELECT * FROM forms WHERE name LIKE '%bill%' AND category = MY REGEX CAPTURE
rendering so something like"
SELECT * FROM forms WHERE name LIKE '%bill%' AND category ='the value i want'
you can use not regex, but hstore extension for this, like:
str := 'thomas-var1="SOME VAL1" thomas-var2="SOME VAL2" thomas-var-3="the value i want"'
str := replace(replace(str, '=', '=>'), '" ', '", ')
select *
from forms
where name like '%bill%' and category = hstore(str)->'thomas-var-3'
Using a subselect and the substring method you should be able to achieve what you want like so:
SELECT *
FROM firstTable
WHERE parentCat = (SELECT cat
FROM secondTable
WHERE cat in substring(column_to_capture_from from 'thomas-var-3="(.+?)' ));
from http://www.regular-expressions.info/postgresql.html
If there is a match, and the regex has one or more capturing groups, the text matched by the first capturing group is returned.

Using WHERE clause to only retrieve results where array field has only ONE element inside

I have a table with various arrays within it like this:
{10574664,10574665,10574679,10574724}
{8616204,10574643,10574644,10574645,10574651,10574688,10574690,10574696,10574708}
{8616208}
{9830397}
{8616203}
{8616204,10574643,10574644,10574645,10574651,10574688,10574690,10574696,10574708}
{8616204,10574643,10574644,10574645,10574651,10574688,10574690,10574696,10574708}
{8616208}
{10574680}
{8616203}
Is there a way to only pull back the records where there is only one element in the array.
The results would look like this:
{8616208}
{9830397}
{8616203}
{8616208}
{10574680}
{8616203}
My query would look something like this
Select * from attr_lookup where target_tcode = help with query here
Use array_length():
SELECT *
FROM attr_lookup
WHERE array_length(target_tcode, 1) = 1;