find space in string postgresql - string

How to find space after words in postgresql:
I have two same strings in my database :
string1
string1
I am trying to find the one with 2 spaces before and one space after.
here are some of the queries I used with their results:
SELECT * FROM table WHERE "column" LIKE '__string1_'; --> *no result*
SELECT * FROM part1 WHERE "column" LIKE '__string1%';
Results:
1) string1 and xyx
2) string1 and string2
3) string1
but I only need string1 with no strings after or before.

There are likely several ways to accomplish this. See PostgreSQL's pattern matching documentation for some examples.
However, I use % to find patterns: select * from table where column ILIKE '%string1%'; would return anything with string1 in it, including the cols with spaces.
You can also try escaping the spaces: select * from table where column ILIKE '\ \ string1\ ';
or, even simpler select * from table where column ILIKE ' string1';
I also use the case insensitive ILIKE as an alternative for a case sensitive LIKE, so case will not matter in your query.

I will just complement the above answer:
Suppose you want to find any space in the column Name in the demo table, then the code would be like:
SELECT * FROM demo
WHERE Name LIKE '% %'
ORDER BY Name
Now, if you want any string 'a' for example inside the column, you would just have the following:
SELECT * FROM demo
WHERE Name LIKE '%a%'
ORDER BY Name
and also, for words that begin with a space, you would just use '_' (in a certain position):
SELECT * FROM demo
WHERE Name LIKE '_a%'
ORDER BY Name

Related

PostgreSQL query where column is represented as a string

I'm using Retool, and trying to run a query where the column value comes from a drop-down list. The value output is a string, so my query looks like this:
select * from accounts where {{dropDownList.value}} ilike {{'%' + account_search_textInput.value + '%'}}
When the query runs, it is as follows:
select * from accounts where "first_name" ilike '%Adam%';
The double quotes around the column name first_name seem to be causing an issue but I don't think I can remove them. Is there any other way to successfully run the query where first_name can represent the column name rather than a string value?

SQL Server: use all the words of a string as separate LIKE parameters (and all words should match)

I have a string containing a certain number of words (it may vary from 1 to many) and I need to find the records of a table which contains ALL those words in any order.
For instances, suppose that my input string is 'yellow blue red' and I have a table with the following records:
1 yellow brown white
2 red blue yellow
3 black blue red
The query should return the record 2.
I know that the basic approach should be something similar to this:
select * from mytable where colors like '%yellow%' and colors like '%blue%' and colors like '%red%'
However I am not being able to figure out how turn the words of the string into separate like parameters.
I have this code that splits the words of the string into a table, but now I am stuck:
DECLARE #mystring varchar(max) = 'yellow blue red';
DECLARE #terms TABLE (term varchar(max));
INSERT INTO #terms
SELECT Split.a.value('.', 'NVARCHAR(MAX)') term FROM (SELECT CAST('<X>'+REPLACE(#mystring, ' ', '</X><X>')+'</X>' AS XML) AS String) AS A CROSS APPLY String.nodes('/X') AS Split(a)
SELECT * FROM #terms
Any idea?
First, put that XML junk in a function:
CREATE FUNCTION dbo.SplitThem
(
#List NVARCHAR(MAX),
#Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN ( SELECT Item = y.i.value(N'(./text())[1]', N'nvarchar(4000)')
FROM ( SELECT x = CONVERT(XML, '<i>'
+ REPLACE(#List, #Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i));
Now you can extract the words in the table, join them to the words in the input string, and discard any that don't have the same count:
DECLARE #mystring varchar(max) = 'red yellow blue';
;WITH src AS
(
SELECT t.id, t.colors, fc = f.c, tc = COUNT(t.id)
FROM dbo.mytable AS t
CROSS APPLY dbo.SplitThem(t.colors, ' ') AS s
INNER JOIN (SELECT Item, c = COUNT(*) OVER()
FROM dbo.SplitThem(#mystring, ' ')) AS f
ON s.Item = f.Item
GROUP BY t.id, t.colors, f.c
)
SELECT * FROM src
WHERE fc = tc;
Output:
id
colors
fc
tc
2
red blue yellow
3
3
Example db<>fiddle
This disregards any possibility of duplicates on either side and ignores the larger overarching issue that this is the least optimal way possible to store sets of things. You have a relational database, use it! Surely you don't think the tags on this question are stored somewhere as the literal string
string sql-server-2012 sql-like
Of course not, these question:tag relationships are stored in a, well, relational table. Splitting strings is for the birds and those with all kinds of CPU and time to spare.
If you are storing a delimited list in a single column then you really need to normalize it out into a separate table.
But assuming you actually want to just do multiple free-form LIKE comparisons, you can do them against a list of values:
select *
from mytable t
where not exists (select 1
from (values
('%yellow%'),
('%blue%'),
('%red%')
) v(search)
where t.colors not like v.search
);
Ideally you should pass these values through as a Table Valued Parameter, then you just put that into your query
select *
from mytable t
where not exists (select 1
from #tmp v
where t.colors not like v.search
);
If you want to simulate an OR semantic rather than AND the change not exists to exists and not like to like.

Node.js + Postgres highest matching to lowest matchig datas

In my node application i am executing a select query.Suppose consider user is giving input as "abcdef" .i will take first 4 letters from that string say "abcd",and i will check for entries matching "abcd" using ILIKE command.
My query is:
client.query("select * from tn_village where level3 ILIKE '%"+substring+"%' OR level4 ILIKE '%"+substring+"%' OR level5 ILIKE '%"+substring+"%' OR level6 ILIKE '%"+substring+"%' OR level7 ILIKE '%"+substring+"%' OR level8 ILIKE '%"+substring+"%' OR level9 ILIKE '%"+substring+"%'" ,function(err,result)
{
res.send(result);
});
Here substring is "abcd"..I am getting result in alphabetical order.. But what i want is i have to show the row which is exactly matching first say row for "abcde" first and then the remaining results,,
Help me to solve this..Thanks in advance..
You could do two levels of ordering where the first level is used to discriminate between exact and partial matches and the second level for alphabetical ordering. For instance,
order by case when test_column = input_string then 0
else 1 end,
input_string
The first level of that ordering will be 0 for exact matches and 1 otherwise. That way if a row matches exactly then the case statement evaluates to 0, which will put that row ahead of inexact matches, for which the case statement evaluates to 1. Then, for all rows with an inexact match the first sorting level will be the same (1), but the second level may differ and will simply give the alphabetic sorting of those rows.

Full-text search with wildcard

I have a table with full text search enabled. But I can't get query the table using wildcard.
select * from products where contains(Description, 'Computer') returns rows with the word "Computer"
select * from products where contains(Description, 'Compute*') [replace "r" with "*"] returns nothing
What's going on?
Assuming SQL Server, add double quotes around the wildcarded expression like so
SELECT *
FROM products
WHERE contains(Description, '"Compute*"')

How to order results based on number of search term matches?

I am using the following InnoDB tables in mysql to describe records that can have multiple searchtags associated with them:
TABLE records
ID
title
desc
TABLE searchTags
ID
name
TABLE recordSearchTags
recordID
searchTagID
To SELECT records based on arbitrary search input, I have a statement that looks sort of like this:
SELECT
recordSearchTags.recordID
FROM
recordSearchTags
LEFT JOIN searchTags
ON recordSearchTags.searchTagID = searchTags.ID
WHERE
searchTags.name LIKE CONCAT('%','$search1','%') OR
searchTags.name LIKE CONCAT('%','$search2','%') OR
searchTags.name LIKE CONCAT('%','$search3','%') OR
searchTags.name LIKE CONCAT('%','$search4','%');
I'd like to ORDER this resultset, so that rows that match with more search terms are displayed in front of rows that match with fewer search terms.
For example, if a row matches all 4 search terms, it will be top of the list. A row that matches only 2 search terms will be somewhere in the middle. And a row that matches just one search term will be at the end.
Any suggestions on what is the best way to do this?
Thanks!
* Replaced answer, since fulltext isn't an option
Alright, it's not pretty, but you should be able to do something like this:
ORDER BY (searchTags.name LIKE CONCAT('%','$search1','%')
+ searchTags.name LIKE CONCAT('%','$search2','%')
+ searchTags.name LIKE CONCAT('%','$search3','%')
+ searchTags.name LIKE CONCAT('%','$search4','%'))
DESC;
LIKE returns 1 on a match or 0 if there is no match, so you should just be able to add the results together.
This isn't very pretty but one way would be to union the 4 likes in 4 statements like
select ... where searchTags.name LIKE CONCAT('%','$search1','%')
union
select ...
and so on. Wrap that in a:
select recordSearchTags.recordID, count(*) from (<inner unions>)
group by recordSearchTags.recordID
order by count(*)

Resources